diff options
Diffstat (limited to 'tools/vscode/packages/server/src/plugins/PluginHost.ts')
-rw-r--r-- | tools/vscode/packages/server/src/plugins/PluginHost.ts | 214 |
1 files changed, 80 insertions, 134 deletions
diff --git a/tools/vscode/packages/server/src/plugins/PluginHost.ts b/tools/vscode/packages/server/src/plugins/PluginHost.ts index 72f098ca1..037dd6e07 100644 --- a/tools/vscode/packages/server/src/plugins/PluginHost.ts +++ b/tools/vscode/packages/server/src/plugins/PluginHost.ts @@ -1,11 +1,4 @@ - -import { - CompletionContext, - CompletionItem, - CompletionList, - Position, - TextDocumentIdentifier, -} from 'vscode-languageserver'; +import { CompletionContext, CompletionItem, CompletionList, Position, TextDocumentIdentifier } from 'vscode-languageserver'; import type { DocumentManager } from '../core/documents'; import type * as d from './interfaces'; import { flatten } from '../utils'; @@ -13,154 +6,107 @@ import { FoldingRange } from 'vscode-languageserver-types'; // eslint-disable-next-line no-shadow enum ExecuteMode { - None, - FirstNonNull, - Collect + None, + FirstNonNull, + Collect, } export class PluginHost { - private plugins: d.Plugin[] = []; - - constructor(private documentsManager: DocumentManager) {} + private plugins: d.Plugin[] = []; - register(plugin: d.Plugin) { - this.plugins.push(plugin); - } + constructor(private documentsManager: DocumentManager) {} - async getCompletions( - textDocument: TextDocumentIdentifier, - position: Position, - completionContext?: CompletionContext - ): Promise<CompletionList> { - const document = this.getDocument(textDocument.uri); - if (!document) { - throw new Error('Cannot call methods on an unopened document'); - } + register(plugin: d.Plugin) { + this.plugins.push(plugin); + } - const completions = ( - await this.execute<CompletionList>( - 'getCompletions', - [document, position, completionContext], - ExecuteMode.Collect - ) - ).filter((completion) => completion != null); - - let flattenedCompletions = flatten(completions.map((completion) => completion.items)); - const isIncomplete = completions.reduce( - (incomplete, completion) => incomplete || completion.isIncomplete, - false as boolean - ); - - return CompletionList.create(flattenedCompletions, isIncomplete); + async getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext): Promise<CompletionList> { + const document = this.getDocument(textDocument.uri); + if (!document) { + throw new Error('Cannot call methods on an unopened document'); } - async resolveCompletion( - textDocument: TextDocumentIdentifier, - completionItem: d.AppCompletionItem - ): Promise<CompletionItem> { - const document = this.getDocument(textDocument.uri); + const completions = (await this.execute<CompletionList>('getCompletions', [document, position, completionContext], ExecuteMode.Collect)).filter( + (completion) => completion != null + ); - if (!document) { - throw new Error('Cannot call methods on an unopened document'); - } - - const result = await this.execute<CompletionItem>( - 'resolveCompletion', - [document, completionItem], - ExecuteMode.FirstNonNull - ); + let flattenedCompletions = flatten(completions.map((completion) => completion.items)); + const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.isIncomplete, false as boolean); - return result ?? completionItem; - } + return CompletionList.create(flattenedCompletions, isIncomplete); + } - async doTagComplete( - textDocument: TextDocumentIdentifier, - position: Position - ): Promise<string | null> { - const document = this.getDocument(textDocument.uri); - if (!document) { - throw new Error('Cannot call methods on an unopened document'); - } + async resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: d.AppCompletionItem): Promise<CompletionItem> { + const document = this.getDocument(textDocument.uri); - return this.execute<string | null>( - 'doTagComplete', - [document, position], - ExecuteMode.FirstNonNull - ); + if (!document) { + throw new Error('Cannot call methods on an unopened document'); } - async getFoldingRanges( - textDocument: TextDocumentIdentifier - ): Promise<FoldingRange[]|null> { - const document = this.getDocument(textDocument.uri); - if (!document) { - throw new Error('Cannot call methods on an unopened document'); - } + const result = await this.execute<CompletionItem>('resolveCompletion', [document, completionItem], ExecuteMode.FirstNonNull); - const foldingRanges = flatten(await this.execute<FoldingRange[]>( - 'getFoldingRanges', - [document], - ExecuteMode.Collect - )).filter((completion) => completion != null) + return result ?? completionItem; + } - return foldingRanges; + async doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null> { + const document = this.getDocument(textDocument.uri); + if (!document) { + throw new Error('Cannot call methods on an unopened document'); } - onWatchFileChanges(onWatchFileChangesParams: any[]): void { - for (const support of this.plugins) { - support.onWatchFileChanges?.(onWatchFileChangesParams); - } - } + return this.execute<string | null>('doTagComplete', [document, position], ExecuteMode.FirstNonNull); + } - private getDocument(uri: string) { - return this.documentsManager.get(uri); + async getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null> { + const document = this.getDocument(textDocument.uri); + if (!document) { + throw new Error('Cannot call methods on an unopened document'); } - private execute<T>( - name: keyof d.LSProvider, - args: any[], - mode: ExecuteMode.FirstNonNull - ): Promise<T | null>; - private execute<T>( - name: keyof d.LSProvider, - args: any[], - mode: ExecuteMode.Collect - ): Promise<T[]>; - private execute(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.None): Promise<void>; - private async execute<T>( - name: keyof d.LSProvider, - args: any[], - mode: ExecuteMode - ): Promise<(T | null) | T[] | void> { - const plugins = this.plugins.filter((plugin) => typeof plugin[name] === 'function'); - - switch (mode) { - case ExecuteMode.FirstNonNull: - for (const plugin of plugins) { - const res = await this.tryExecutePlugin(plugin, name, args, null); - if (res != null) { - return res; - } - } - return null; - case ExecuteMode.Collect: - return Promise.all( - plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, [])) - ); - case ExecuteMode.None: - await Promise.all( - plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null)) - ); - return; - } - } + const foldingRanges = flatten(await this.execute<FoldingRange[]>('getFoldingRanges', [document], ExecuteMode.Collect)).filter((completion) => completion != null); + + return foldingRanges; + } - private async tryExecutePlugin(plugin: any, fnName: string, args: any[], failValue: any) { - try { - return await plugin[fnName](...args); - } catch (e) { - console.error(e); - return failValue; + onWatchFileChanges(onWatchFileChangesParams: any[]): void { + for (const support of this.plugins) { + support.onWatchFileChanges?.(onWatchFileChangesParams); + } + } + + private getDocument(uri: string) { + return this.documentsManager.get(uri); + } + + private execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.FirstNonNull): Promise<T | null>; + private execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.Collect): Promise<T[]>; + private execute(name: keyof d.LSProvider, args: any[], mode: ExecuteMode.None): Promise<void>; + private async execute<T>(name: keyof d.LSProvider, args: any[], mode: ExecuteMode): Promise<(T | null) | T[] | void> { + const plugins = this.plugins.filter((plugin) => typeof plugin[name] === 'function'); + + switch (mode) { + case ExecuteMode.FirstNonNull: + for (const plugin of plugins) { + const res = await this.tryExecutePlugin(plugin, name, args, null); + if (res != null) { + return res; + } } + return null; + case ExecuteMode.Collect: + return Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, []))); + case ExecuteMode.None: + await Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null))); + return; + } + } + + private async tryExecutePlugin(plugin: any, fnName: string, args: any[], failValue: any) { + try { + return await plugin[fnName](...args); + } catch (e) { + console.error(e); + return failValue; } + } } |