Skip to content

Commit

Permalink
refactor: remove LanguageServicePlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Apr 21, 2022
1 parent 217abe1 commit 5031e02
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 135 deletions.
Expand Up @@ -42,7 +42,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCallHierarchyData = {
uri,
originalItem: item,
pluginId: plugin.id,
pluginId: context.getPluginId(plugin),
sourceMap: sourceMap ? {
embeddedDocumentUri: sourceMap.mappedDocument.uri,
} : undefined,
Expand Down
Expand Up @@ -81,7 +81,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCodeActionData = {
uri,
originalItem: _codeAction,
pluginId: plugin.id,
pluginId: context.getPluginId(plugin),
sourceMap: sourceMap ? {
embeddedDocumentUri: sourceMap.mappedDocument.uri,
} : undefined,
Expand Down
Expand Up @@ -28,9 +28,9 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCodeLensData = {
uri,
originalItem: item,
pluginId: plugin.id,
pluginId: context.getPluginId(plugin),
};
const commandArgs: ExecutePluginCommandArgs | undefined = item.command ? [uri, plugin.id, item.command] : undefined;
const commandArgs: ExecutePluginCommandArgs | undefined = item.command ? [uri, context.getPluginId(plugin), item.command] : undefined;
const codeLens: vscode.CodeLens = {
...item,
command: item.command && commandArgs ? {
Expand Down
Expand Up @@ -26,7 +26,7 @@ export function register(context: LanguageServiceRuntimeContext) {
command: resolvedOriginalItem.command ? {
...resolvedOriginalItem.command,
command: executePluginCommand,
arguments: <ExecutePluginCommandArgs>[data.uri, plugin.id, resolvedOriginalItem.command],
arguments: <ExecutePluginCommandArgs>[data.uri, context.getPluginId(plugin), resolvedOriginalItem.command],
} : undefined,
range: item.range, // range already transform in codeLens request
};
Expand Down
14 changes: 7 additions & 7 deletions packages/vue-language-service/src/languageFeatures/complete.ts
@@ -1,8 +1,8 @@
import { transformCompletionItem } from '@volar/transforms';
import type { EmbeddedLanguageServicePlugin } from '@volar/vue-language-service-types';
import * as vscode from 'vscode-languageserver-protocol';
import type { LanguageServiceRuntimeContext } from '../types';
import { visitEmbedded } from '../utils/definePlugin';
import { LanguageServicePlugin } from '../languageService';

export interface PluginCompletionData {
uri: string,
Expand All @@ -21,7 +21,7 @@ export function register(context: LanguageServiceRuntimeContext) {
sourceMap: {
embeddedDocumentUri: string;
} | undefined,
plugin: LanguageServicePlugin,
plugin: EmbeddedLanguageServicePlugin,
list: vscode.CompletionList,
}[],
mainCompletion: {
Expand Down Expand Up @@ -68,7 +68,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCompletionData = {
uri,
originalItem: item,
pluginId: cacheData.plugin.id,
pluginId: context.getPluginId(cacheData.plugin),
sourceMap: {
embeddedDocumentUri: sourceMap.mappedDocument.uri,
},
Expand Down Expand Up @@ -103,7 +103,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCompletionData = {
uri,
originalItem: item,
pluginId: cacheData.plugin.id,
pluginId: context.getPluginId(cacheData.plugin),
sourceMap: undefined,
};
return {
Expand Down Expand Up @@ -161,7 +161,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCompletionData = {
uri,
originalItem: item,
pluginId: plugin.id,
pluginId: context.getPluginId(plugin),
sourceMap: {
embeddedDocumentUri: sourceMap.mappedDocument.uri,
}
Expand Down Expand Up @@ -223,7 +223,7 @@ export function register(context: LanguageServiceRuntimeContext) {
const data: PluginCompletionData = {
uri,
originalItem: item,
pluginId: plugin.id,
pluginId: context.getPluginId(plugin),
sourceMap: undefined,
};
return {
Expand All @@ -239,7 +239,7 @@ export function register(context: LanguageServiceRuntimeContext) {

return combineCompletionList(cache.data.map(cacheData => cacheData.list));

function sortPlugins(a: LanguageServicePlugin, b: LanguageServicePlugin) {
function sortPlugins(a: EmbeddedLanguageServicePlugin, b: EmbeddedLanguageServicePlugin) {
return (b.complete?.isAdditional ? -1 : 1) - (a.complete?.isAdditional ? -1 : 1);
}

Expand Down
Expand Up @@ -101,7 +101,8 @@ export function register(context: LanguageServiceRuntimeContext) {
if (await isCancel?.())
return;

const pluginCache = cacheMap.get(plugin.id) ?? cacheMap.set(plugin.id, new Map()).get(plugin.id)!;
const pluginId = context.getPluginId(plugin);
const pluginCache = cacheMap.get(pluginId) ?? cacheMap.set(pluginId, new Map()).get(pluginId)!;
const cache = pluginCache.get(document.uri);
const tsProjectVersion = isTs ? context.getTsLs().__internal__.host.getProjectVersion?.() : undefined;

Expand Down
195 changes: 78 additions & 117 deletions packages/vue-language-service/src/languageService.ts
Expand Up @@ -54,17 +54,6 @@ import useVueTemplateLanguagePlugin, { semanticTokenTypes as vueTemplateSemantic

export interface LanguageService extends ReturnType<typeof createLanguageService> { }

export type LanguageServicePlugin = ReturnType<typeof defineLanguageServicePlugin>;

let pluginId = 0;

function defineLanguageServicePlugin<T extends EmbeddedLanguageServicePlugin>(plugin: T) {
return {
id: pluginId++,
...plugin,
};
}

export function getSemanticTokenLegend() {

const tsLegend = ts2.getSemanticTokenLegend();
Expand All @@ -86,7 +75,7 @@ export function createLanguageService(
fileSystemProvider: html.FileSystemProvider | undefined,
schemaRequestService: json.SchemaRequestService | undefined,
configurationHost: ConfigurationHost | undefined,
_customPlugins: EmbeddedLanguageServicePlugin[],
customPlugins: EmbeddedLanguageServicePlugin[],
getNameCases?: (uri: string) => Promise<{
tag: 'both' | 'kebabCase' | 'pascalCase',
attr: 'kebabCase' | 'camelCase',
Expand All @@ -112,13 +101,10 @@ export function createLanguageService(
const documentVersions = new Map<string, number>();

// plugins
const customPlugins = _customPlugins.map(plugin => defineLanguageServicePlugin(plugin));
const vuePlugin = defineLanguageServicePlugin(
useVuePlugin({
getVueDocument: (document) => vueDocuments.get(document.uri),
tsLs,
}),
);
const vuePlugin = useVuePlugin({
getVueDocument: (document) => vueDocuments.get(document.uri),
tsLs,
});
const vueTemplateHtmlPlugin = _useVueTemplateLanguagePlugin(
'html',
useHtmlPlugin({
Expand All @@ -134,21 +120,15 @@ export function createLanguageService(
documentContext,
}),
);
const cssPlugin = defineLanguageServicePlugin(
useCssPlugin({
documentContext,
fileSystemProvider,
}),
);
const jsonPlugin = defineLanguageServicePlugin(
useJsonPlugin({
schema: undefined, // TODO
schemaRequestService,
}),
);
const emmetPlugin = defineLanguageServicePlugin(
useEmmetPlugin(),
);
const cssPlugin = useCssPlugin({
documentContext,
fileSystemProvider,
});
const jsonPlugin = useJsonPlugin({
schema: undefined, // TODO
schemaRequestService,
});
const emmetPlugin = useEmmetPlugin();
const scriptTsPlugin = useTsPlugins(
tsLs,
false,
Expand All @@ -163,54 +143,40 @@ export function createLanguageService(
includeCompletionsForImportStatements: false,
}),
);
const autoDotValuePlugin = defineLanguageServicePlugin(
useAutoDotValuePlugin({
ts,
getTsLs: () => tsLs,
}),
);
const referencesCodeLensPlugin = defineLanguageServicePlugin(
useReferencesCodeLensPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
findReference: async (...args) => findReferences_internal(...args),
}),
);
const htmlPugConversionsPlugin = defineLanguageServicePlugin(
useHtmlPugConversionsPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
}),
);
const scriptSetupConversionsPlugin = defineLanguageServicePlugin(
useScriptSetupConversionsPlugin({
ts,
getVueDocument: (uri) => vueDocuments.get(uri),
doCodeActions: async (...args) => doCodeActions_internal(...args),
doCodeActionResolve: async (...args) => doCodeActionResolve_internal(...args),
}),
);
const refSugarConversionsPlugin = defineLanguageServicePlugin(
useRefSugarConversionsPlugin({
ts,
getVueDocument: (uri) => vueDocuments.get(uri),
doCodeActions: async (...args) => doCodeActions_internal(...args),
doCodeActionResolve: async (...args) => doCodeActionResolve_internal(...args),
findReferences: async (...args) => findReferences_internal(...args),
doValidation: async (...args) => doValidation_internal(...args),
doRename: async (...args) => doRename_internal(...args),
findTypeDefinition: async (...args) => findTypeDefinition_internal(...args),
scriptTsLs: tsLs,
}),
);
const tagNameCasingConversionsPlugin = defineLanguageServicePlugin(
useTagNameCasingConversionsPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
findReferences: async (...args) => findReferences_internal(...args),
}),
);

const allPlugins = new Map<number, LanguageServicePlugin>();
const autoDotValuePlugin = useAutoDotValuePlugin({
ts,
getTsLs: () => tsLs,
});
const referencesCodeLensPlugin = useReferencesCodeLensPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
findReference: async (...args) => findReferences_internal(...args),
});
const htmlPugConversionsPlugin = useHtmlPugConversionsPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
});
const scriptSetupConversionsPlugin = useScriptSetupConversionsPlugin({
ts,
getVueDocument: (uri) => vueDocuments.get(uri),
doCodeActions: async (...args) => doCodeActions_internal(...args),
doCodeActionResolve: async (...args) => doCodeActionResolve_internal(...args),
});
const refSugarConversionsPlugin = useRefSugarConversionsPlugin({
ts,
getVueDocument: (uri) => vueDocuments.get(uri),
doCodeActions: async (...args) => doCodeActions_internal(...args),
doCodeActionResolve: async (...args) => doCodeActionResolve_internal(...args),
findReferences: async (...args) => findReferences_internal(...args),
doValidation: async (...args) => doValidation_internal(...args),
doRename: async (...args) => doRename_internal(...args),
findTypeDefinition: async (...args) => findTypeDefinition_internal(...args),
scriptTsLs: tsLs,
});
const tagNameCasingConversionsPlugin = useTagNameCasingConversionsPlugin({
getVueDocument: (uri) => vueDocuments.get(uri),
findReferences: async (...args) => findReferences_internal(...args),
});

for (const plugin of [
const allPlugins = [
...customPlugins,
vuePlugin,
cssPlugin,
Expand All @@ -225,9 +191,7 @@ export function createLanguageService(
refSugarConversionsPlugin,
tagNameCasingConversionsPlugin,
scriptTsPlugin,
]) {
allPlugins.set(plugin.id, plugin);
}
];

const stylesheetExtra = createStylesheetExtra(cssPlugin);
const context: LanguageServiceRuntimeContext = {
Expand All @@ -251,7 +215,8 @@ export function createLanguageService(
// put emmet plugin at latest to fix https://github.com/johnsoncodehk/volar/issues/1088
emmetPlugin,
],
getPluginById: id => allPlugins.get(id),
getPluginId: plugin => allPlugins.indexOf(plugin),
getPluginById: id => allPlugins[id],
};
const _callHierarchy = callHierarchy.register(context);
const findReferences_internal = defineInternalApi(references.register(context));
Expand Down Expand Up @@ -377,41 +342,37 @@ export function createLanguageService(
}
}
function _useVueTemplateLanguagePlugin<T extends ReturnType<typeof useHtmlPlugin> | ReturnType<typeof usePugPlugin>>(languageId: string, templateLanguagePlugin: T) {
return defineLanguageServicePlugin(
useVueTemplateLanguagePlugin({
ts,
templateLanguagePlugin,
getSemanticTokenLegend,
getScanner: (document): html.Scanner | undefined => {
if (document.languageId === 'html') {
return templateLanguagePlugin.htmlLs.createScanner(document.getText());
}
else if (document.languageId === 'jade') {
const pugDocument = 'getPugDocument' in templateLanguagePlugin ? templateLanguagePlugin.getPugDocument(document) : undefined;
if (pugDocument) {
return 'pugLs' in templateLanguagePlugin ? templateLanguagePlugin.pugLs.createScanner(pugDocument) : undefined;
}
return useVueTemplateLanguagePlugin({
ts,
templateLanguagePlugin,
getSemanticTokenLegend,
getScanner: (document): html.Scanner | undefined => {
if (document.languageId === 'html') {
return templateLanguagePlugin.htmlLs.createScanner(document.getText());
}
else if (document.languageId === 'jade') {
const pugDocument = 'getPugDocument' in templateLanguagePlugin ? templateLanguagePlugin.getPugDocument(document) : undefined;
if (pugDocument) {
return 'pugLs' in templateLanguagePlugin ? templateLanguagePlugin.pugLs.createScanner(pugDocument) : undefined;
}
},
tsLs,
isSupportedDocument: (document) => document.languageId === languageId,
getNameCases,
vueLsHost,
vueDocuments,
tsSettings,
tsRuntime,
}),
);
}
},
tsLs,
isSupportedDocument: (document) => document.languageId === languageId,
getNameCases,
vueLsHost,
vueDocuments,
tsSettings,
tsRuntime,
});
}
function useTsPlugins(tsLs: ts2.LanguageService, isTemplatePlugin: boolean, getBaseCompletionOptions: (uri: string) => ts.GetCompletionsAtPositionOptions) {
const _languageSupportPlugin = defineLanguageServicePlugin(
useTsPlugin({
tsVersion: ts.version,
getTsLs: () => tsLs,
getBaseCompletionOptions,
}),
);
const languageSupportPlugin: LanguageServicePlugin = isTemplatePlugin ? {
const _languageSupportPlugin = useTsPlugin({
tsVersion: ts.version,
getTsLs: () => tsLs,
getBaseCompletionOptions,
});
const languageSupportPlugin: EmbeddedLanguageServicePlugin = isTemplatePlugin ? {
..._languageSupportPlugin,
complete: {
..._languageSupportPlugin.complete,
Expand Down
6 changes: 3 additions & 3 deletions packages/vue-language-service/src/types.ts
@@ -1,7 +1,6 @@
import type * as ts2 from '@volar/typescript-language-service';
import { EmbeddedLanguageServicePlugin } from '@volar/vue-language-service-types';
import type { TextDocument } from 'vscode-languageserver-textdocument';
import { LanguageServicePlugin } from './languageService';
import { VueDocument, VueDocuments } from './vueDocuments';

export { LanguageServiceHost } from '@volar/vue-typescript';
Expand All @@ -17,7 +16,8 @@ export type DocumentServiceRuntimeContext = {
export type LanguageServiceRuntimeContext = {
vueDocuments: VueDocuments,
getTextDocument(uri: string): TextDocument | undefined,
getPlugins(): LanguageServicePlugin[],
getPluginById(id: number): LanguageServicePlugin | undefined,
getPlugins(): EmbeddedLanguageServicePlugin[],
getPluginId(plugin: EmbeddedLanguageServicePlugin): number,
getPluginById(id: number): EmbeddedLanguageServicePlugin | undefined,
getTsLs(): ts2.LanguageService;
};

0 comments on commit 5031e02

Please sign in to comment.