Skip to content

Commit 783b9ec

Browse files
committed
extension/src/language: create interactive list enum middleware
The interactive language client accept an interactive middleware as input. The interactive middleware allow the extension developer to specify middleware for interactive list enum request. By default (if middleware not provided), the client call the default "next" function. Otherwise (if provided), the client pass the "parameter" and the "next" function which allows the caller to decide whether / how the caller want to call the "next" function. The pattern looks very similar to vscode-languageserver-node https://github.com/microsoft/vscode-languageserver-node/blob/main/client/src/common/documentHighlight.ts Example & validation: CL 781460 For golang/go#76331 Change-Id: I124ad8681bd6b926be4e517ef563832a6eb59440 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/781221 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Madeline Kalil <mkalil@google.com>
1 parent 14abd06 commit 783b9ec

2 files changed

Lines changed: 70 additions & 13 deletions

File tree

extension/src/language/form.ts

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66

77
import * as vscode from 'vscode';
88
import { InitializeParams } from 'vscode-languageserver-protocol';
9-
import { LanguageClient, RequestType, ServerOptions, LanguageClientOptions } from 'vscode-languageclient/node';
9+
import {
10+
LanguageClient,
11+
RequestType,
12+
ServerOptions,
13+
LanguageClientOptions,
14+
Middleware
15+
} from 'vscode-languageclient/node';
1016

1117
// ----------------------------------------------------------------------------
1218
// Form Field Type Definitions
@@ -283,12 +289,42 @@ export interface InteractiveListEnumParams {
283289
query: string;
284290
}
285291

292+
/**
293+
* InteractiveLanguageClientOptions extends LanguageClientOptions with
294+
* interactive middleware support.
295+
*/
296+
export interface InteractiveLanguageClientOptions extends LanguageClientOptions {
297+
middleware?: InteractiveMiddleware;
298+
}
299+
300+
/**
301+
* InteractiveMiddleware extends the standard Language Server Protocol (LSP)
302+
* `Middleware` to support interactive refactoring workflows.
303+
*
304+
* This allows extension authors to intercept key lifecycle events of the
305+
* interactive dialog, including the command resolution phase, the execution of
306+
* the validated command, and dynamic enumeration requests for lazy-loaded options.
307+
*/
308+
export type InteractiveMiddleware = Middleware & InteractiveListEnumMiddleware;
309+
310+
export interface InteractiveListEnumSignature {
311+
(this: void, param: InteractiveListEnumParams): vscode.ProviderResult<FormEnumEntry[]>;
312+
}
313+
314+
export interface InteractiveListEnumMiddleware {
315+
interactiveListEnum?: (
316+
this: void,
317+
param: InteractiveListEnumParams,
318+
next: InteractiveListEnumSignature
319+
) => vscode.ProviderResult<FormEnumEntry[]>;
320+
}
321+
286322
export class InteractiveLanguageClient extends LanguageClient {
287323
constructor(
288324
id: string,
289325
name: string,
290326
serverOptions: ServerOptions,
291-
clientOptions: LanguageClientOptions,
327+
clientOptions: InteractiveLanguageClientOptions,
292328
forceDebug?: boolean
293329
) {
294330
super(id, name, serverOptions, clientOptions, forceDebug);
@@ -405,14 +441,35 @@ export class InteractiveLanguageClient extends LanguageClient {
405441
});
406442
}
407443

408-
// Queries the language server to dynamically retrieve enumeration entries for
409-
// interactive form fields of type 'lazyEnum'.
410-
async InteractiveListEnum(param: InteractiveListEnumParams): Promise<FormEnumEntry[] | undefined> {
411-
const requestType = new RequestType<InteractiveListEnumParams, FormEnumEntry[], void>('interactive/listEnum');
412-
return this.sendRequest<FormEnumEntry[]>('interactive/listEnum', param).then(undefined, (error) => {
413-
return this.handleFailedRequest(requestType, undefined, error, undefined);
414-
});
415-
}
444+
/**
445+
* Queries the language server to dynamically retrieve enumeration entries for
446+
* interactive form fields of type 'lazyEnum'.
447+
*
448+
* This field uses an arrow function to preserve the lexical `this` context of
449+
* the client. It routes the query through the `interactiveListEnum`
450+
* middleware hook if registered, falling back to the default
451+
* `'interactive/listEnum'` LSP request.
452+
*
453+
* @param param The query parameters, including the data source name, static
454+
* config, and filter string.
455+
* @returns A provider result resolving to the matching list of form
456+
* enumeration entries.
457+
*/
458+
private interactiveListEnum = (param: InteractiveListEnumParams): vscode.ProviderResult<FormEnumEntry[]> => {
459+
const _interactiveListEnum: InteractiveListEnumSignature = (param) => {
460+
const requestType = new RequestType<InteractiveListEnumParams, FormEnumEntry[], void>(
461+
'interactive/listEnum'
462+
);
463+
return this.sendRequest<FormEnumEntry[]>('interactive/listEnum', param).then(undefined, (error) => {
464+
return this.handleFailedRequest(requestType, undefined, error, undefined);
465+
});
466+
};
467+
468+
const middleware = this.clientOptions.middleware as InteractiveMiddleware | undefined;
469+
return middleware?.interactiveListEnum
470+
? middleware.interactiveListEnum(param, _interactiveListEnum)
471+
: _interactiveListEnum(param);
472+
};
416473

417474
/**
418475
* Iterates through the provided form fields and prompts the user for input
@@ -483,7 +540,7 @@ export class InteractiveLanguageClient extends LanguageClient {
483540
config: config,
484541
query: query
485542
};
486-
const response = await this.InteractiveListEnum(params);
543+
const response = await this.interactiveListEnum(params);
487544

488545
if (!response) {
489546
quickPick.items = [];

extension/src/language/goLanguageServer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import { GoDocumentSelector } from '../goMode';
6969
import { COMMAND as GOPLS_ADD_TEST_COMMAND } from '../goGenerateTests';
7070
import { COMMAND as GOPLS_MODIFY_TAGS_COMMAND } from '../goModifytags';
7171
import { TelemetryKey, telemetryReporter } from '../goTelemetry';
72-
import { InteractiveExecuteCommandParams, InteractiveLanguageClient } from './form';
72+
import { InteractiveExecuteCommandParams, InteractiveLanguageClient, InteractiveMiddleware } from './form';
7373

7474
export interface LanguageServerConfig {
7575
serverName: string;
@@ -839,7 +839,7 @@ export async function buildLanguageClient(
839839
return null;
840840
}
841841
}
842-
}
842+
} as InteractiveMiddleware
843843
} as LanguageClientOptions,
844844
onDidChangeVulncheckResultEmitter
845845
);

0 commit comments

Comments
 (0)