|
6 | 6 |
|
7 | 7 | import * as vscode from 'vscode'; |
8 | 8 | 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'; |
10 | 16 |
|
11 | 17 | // ---------------------------------------------------------------------------- |
12 | 18 | // Form Field Type Definitions |
@@ -283,12 +289,42 @@ export interface InteractiveListEnumParams { |
283 | 289 | query: string; |
284 | 290 | } |
285 | 291 |
|
| 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 | + |
286 | 322 | export class InteractiveLanguageClient extends LanguageClient { |
287 | 323 | constructor( |
288 | 324 | id: string, |
289 | 325 | name: string, |
290 | 326 | serverOptions: ServerOptions, |
291 | | - clientOptions: LanguageClientOptions, |
| 327 | + clientOptions: InteractiveLanguageClientOptions, |
292 | 328 | forceDebug?: boolean |
293 | 329 | ) { |
294 | 330 | super(id, name, serverOptions, clientOptions, forceDebug); |
@@ -405,14 +441,35 @@ export class InteractiveLanguageClient extends LanguageClient { |
405 | 441 | }); |
406 | 442 | } |
407 | 443 |
|
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 | + }; |
416 | 473 |
|
417 | 474 | /** |
418 | 475 | * Iterates through the provided form fields and prompts the user for input |
@@ -483,7 +540,7 @@ export class InteractiveLanguageClient extends LanguageClient { |
483 | 540 | config: config, |
484 | 541 | query: query |
485 | 542 | }; |
486 | | - const response = await this.InteractiveListEnum(params); |
| 543 | + const response = await this.interactiveListEnum(params); |
487 | 544 |
|
488 | 545 | if (!response) { |
489 | 546 | quickPick.items = []; |
|
0 commit comments