summaryrefslogtreecommitdiff
path: root/tools/language-server/src/plugins/PluginHost.ts
diff options
context:
space:
mode:
Diffstat (limited to 'tools/language-server/src/plugins/PluginHost.ts')
-rw-r--r--tools/language-server/src/plugins/PluginHost.ts178
1 files changed, 0 insertions, 178 deletions
diff --git a/tools/language-server/src/plugins/PluginHost.ts b/tools/language-server/src/plugins/PluginHost.ts
deleted file mode 100644
index 3ad21a21c..000000000
--- a/tools/language-server/src/plugins/PluginHost.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import type {
- CancellationToken,
- CompletionContext,
- CompletionItem,
- DefinitionLink,
- Location,
- Position,
- SignatureHelp,
- SignatureHelpContext,
- TextDocumentIdentifier,
-} from 'vscode-languageserver';
-import type { DocumentManager } from '../core/documents';
-import type * as d from './interfaces';
-import { flatten } from '../utils';
-import { CompletionList } from 'vscode-languageserver';
-import { Hover, FoldingRange } from 'vscode-languageserver-types';
-
-enum ExecuteMode {
- None,
- FirstNonNull,
- Collect,
-}
-
-interface PluginHostConfig {
- filterIncompleteCompletions: boolean;
- definitionLinkSupport: boolean;
-}
-
-export class PluginHost {
- private plugins: d.Plugin[] = [];
- private pluginHostConfig: PluginHostConfig = {
- filterIncompleteCompletions: true,
- definitionLinkSupport: false,
- };
-
- constructor(private documentsManager: DocumentManager) {}
-
- initialize(pluginHostConfig: PluginHostConfig) {
- this.pluginHostConfig = pluginHostConfig;
- }
-
- register(plugin: d.Plugin) {
- this.plugins.push(plugin);
- }
-
- 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');
- }
-
- 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 resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: d.AppCompletionItem): Promise<CompletionItem> {
- 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);
-
- return result ?? completionItem;
- }
-
- async doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
-
- return this.execute<Hover>('doHover', [document, position], ExecuteMode.FirstNonNull);
- }
-
- 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');
- }
-
- return this.execute<string | null>('doTagComplete', [document, position], ExecuteMode.FirstNonNull);
- }
-
- 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 foldingRanges = flatten(await this.execute<FoldingRange[]>('getFoldingRanges', [document], ExecuteMode.Collect)).filter((completion) => completion != null);
-
- return foldingRanges;
- }
-
- async getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
-
- const definitions = flatten(await this.execute<DefinitionLink[]>('getDefinitions', [document, position], ExecuteMode.Collect));
-
- if (this.pluginHostConfig.definitionLinkSupport) {
- return definitions;
- } else {
- return definitions.map((def) => <Location>{ range: def.targetSelectionRange, uri: def.targetUri });
- }
- }
-
- async getSignatureHelp(
- textDocument: TextDocumentIdentifier,
- position: Position,
- context: SignatureHelpContext | undefined,
- cancellationToken: CancellationToken
- ): Promise<SignatureHelp | null> {
- const document = this.getDocument(textDocument.uri);
- if (!document) {
- throw new Error('Cannot call methods on an unopened document');
- }
-
- return await this.execute<any>('getSignatureHelp', [document, position, context, cancellationToken], ExecuteMode.FirstNonNull);
- }
-
- 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) => {
- let ret = this.tryExecutePlugin(plugin, name, args, []);
- return ret;
- })
- );
- 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;
- }
- }
-}