дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(http-client): Generate requests from Spring Web mappings (#104)
Spring MVC/WebFlux mapping methods (Java and Kotlin) in @RestController / @Controller classes get a gutter icon with "Generate Request in HTTP Client", and the class line gets "Generate Requests for Controller"; both are also actions (`http.generateSpringRequest`, `http.generateSpringControllerRequests`) in Find Action, the editor menu and ⌥↵. Requests are appended to the `generated-requests.http` scratch and opened at the new request.
The URL combines class and method paths ({id} and {id:regex} → {{id}}), with host, port and context path from application.properties / .yml (default http://localhost:8080). @RequestParam, @RequestHeader, params/headers, consumes/produces and @RequestBody (JSON skeleton from the body type, nested one level) are mapped; same-file constants are resolved. Adds an `intentionProviders` editor facet so features can contribute ⌥↵ items.
Fixes #100
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
1 джерело
a065189516
коміт
14f72fc307
9 files changed
+1824
-7
No files matched your search
@@ -283,6 +283,28 @@ export function contributedAt<T>(state: EditorState, key: string, pos: number):
|
||||
return state.languageDataAt<T>(key, pos)[0];
|
||||
}
|
||||
|
||||
/** A context action a feature offers at the caret, listed by Show Context Actions (⌥↵) before the language server's. */
|
||||
export interface ContributedIntention {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
run: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
/** Providers of `ContributedIntention`s for the caret of `view` (cheap and synchronous: also drives the light bulb). */
|
||||
export const intentionProviders = Facet.define<(view: EditorView) => ContributedIntention[]>();
|
||||
|
||||
export function contributedIntentions(view: EditorView): ContributedIntention[] {
|
||||
return view.state.facet(intentionProviders).flatMap((p) => {
|
||||
try {
|
||||
return p(view);
|
||||
} catch (e) {
|
||||
console.error("intention provider failed", e);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- navigation history ------------------------------------------------------
|
||||
|
||||
/** One entry of the Back/Forward (⌘[ / ⌘]) history. 0-based line, UTF-16 col. */
|
||||
|
||||
@@ -7,7 +7,7 @@ import { StateEffect, StateField, type Extension } from "@codemirror/state";
|
||||
import { EditorView, ViewPlugin, type ViewUpdate } from "@codemirror/view";
|
||||
import { forEachDiagnostic } from "@codemirror/lint";
|
||||
import { commands, isCancelled, type CodeAction } from "@/platform/ipc";
|
||||
import { whenSynced } from "@/editor/api";
|
||||
import { contributedIntentions, whenSynced } from "@/editor/api";
|
||||
import { shortcutLabel } from "@/platform/keymap";
|
||||
import { debounce, docOf, isUnavailable, lspRequest, reportLspError } from "./lsp";
|
||||
import { offsetsToRange } from "./positions";
|
||||
@@ -207,8 +207,8 @@ export function withInspectionControls(view: EditorView, items: ListPopupItem[])
|
||||
/** ⌥↵ */
|
||||
export async function showIntentions(view: EditorView) {
|
||||
try {
|
||||
// Typo fixes come first and need no language server.
|
||||
const local = spellingIntentions(view);
|
||||
// Typo fixes and feature-contributed actions come first and need no language server.
|
||||
const local: ListPopupItem[] = [...spellingIntentions(view), ...contributedIntentions(view)];
|
||||
let actions: CodeAction[] = [];
|
||||
let failure: { error: unknown } | null = null;
|
||||
try {
|
||||
@@ -338,20 +338,21 @@ const bulbPlugin = ViewPlugin.fromClass(
|
||||
if (!doc || doc.readOnly || !this.view.dom.isConnected) return;
|
||||
const state = this.view.state;
|
||||
const typoFix = spellingIntentions(this.view).length > 0;
|
||||
const local = typoFix || contributedIntentions(this.view).length > 0;
|
||||
const backoff = serverBackoff.active(doc.doc);
|
||||
if (backoff && !typoFix) return;
|
||||
if (backoff && !local) return;
|
||||
let actions: CodeAction[] = [];
|
||||
if (!backoff) {
|
||||
try {
|
||||
actions = await fetchIntentions(this.view);
|
||||
} catch (e) {
|
||||
if (isUnavailable(e)) serverBackoff.mark(doc.doc);
|
||||
if (!typoFix) return;
|
||||
if (!local) return;
|
||||
}
|
||||
}
|
||||
if (this.view.state.doc !== state.doc || !this.view.state.selection.eq(state.selection)) return;
|
||||
const line = state.doc.lineAt(state.selection.main.head).number;
|
||||
const any = actions.length > 0 || typoFix;
|
||||
const any = actions.length > 0 || local;
|
||||
this.view.dispatch({
|
||||
effects: setBulb.of(any ? { line, quickFix: typoFix || actions.some(isQuickFix) } : null),
|
||||
});
|
||||
|
||||
Reference in new issue
Заблокувати користувача