Skip to content

Commit 4820a7c

Browse files
committed
refactor: simplify language server params for vue
1 parent f4a5179 commit 4820a7c

File tree

30 files changed

+526
-599
lines changed

30 files changed

+526
-599
lines changed
Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createTsLanguageModule, createHtmlLanguageModule, HTMLTemplateFile } from '@volar-examples/angular-language-core';
22
import createTsPlugin from '@volar-plugins/typescript';
33
import { createLanguageServer, LanguageServerPlugin } from '@volar/language-server/node';
4-
import type { LanguageServicePlugin, DocumentsAndSourceMaps, Diagnostic } from '@volar/language-service';
4+
import type { LanguageServicePlugin, Diagnostic } from '@volar/language-service';
55

66
const plugin: LanguageServerPlugin = () => ({
77
extraFileExtensions: [{ extension: 'html', isMixedContent: true, scriptKind: 7 }],
@@ -15,41 +15,35 @@ const plugin: LanguageServerPlugin = () => ({
1515
}
1616
return [];
1717
},
18-
getServicePlugins(_host, service) {
18+
getServicePlugins() {
1919
return [
2020
createTsPlugin(),
21-
createNgTemplateLsPlugin(service.context.documents),
21+
ngTemplatePlugin,
2222
];
2323
},
2424
});
2525

26-
function createNgTemplateLsPlugin(docs: DocumentsAndSourceMaps): LanguageServicePlugin {
26+
const ngTemplatePlugin: LanguageServicePlugin = (context) => ({
2727

28-
return () => {
28+
validation: {
2929

30-
return {
30+
onSyntactic(document) {
3131

32-
validation: {
32+
const file = context.documents.getVirtualFileByUri(document.uri);
3333

34-
onSyntactic(document) {
35-
36-
const file = docs.getRootFileBySourceFileUri(document.uri);
37-
38-
if (file instanceof HTMLTemplateFile) {
39-
return (file.parsed.errors ?? []).map<Diagnostic>(error => ({
40-
range: {
41-
start: { line: error.span.start.line, character: error.span.start.col },
42-
end: { line: error.span.end.line, character: error.span.end.col },
43-
},
44-
severity: error.level === 1 ? 1 : 2,
45-
source: 'ng-template',
46-
message: error.msg,
47-
}));
48-
}
49-
},
34+
if (file instanceof HTMLTemplateFile) {
35+
return (file.parsed.errors ?? []).map<Diagnostic>(error => ({
36+
range: {
37+
start: { line: error.span.start.line, character: error.span.start.col },
38+
end: { line: error.span.end.line, character: error.span.end.col },
39+
},
40+
severity: error.level === 1 ? 1 : 2,
41+
source: 'ng-template',
42+
message: error.msg,
43+
}));
5044
}
51-
};
52-
};
53-
}
45+
},
46+
}
47+
});
5448

5549
createLanguageServer([plugin]);

examples/vue-and-svelte-language-server/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import useTsPlugin from '@volar-plugins/typescript';
33
import { createLanguageServer, LanguageServerInitializationOptions, LanguageServerPlugin } from '@volar/language-server/node';
44
import * as vue from '@volar/vue-language-core';
55

6-
const plugin: LanguageServerPlugin<LanguageServerInitializationOptions, vue.LanguageServiceHost> = () => {
6+
const plugin: LanguageServerPlugin<LanguageServerInitializationOptions, vue.VueLanguageServiceHost> = () => {
77
return {
88
extraFileExtensions: [
99
{ extension: 'vue', isMixedContent: true, scriptKind: 7 },

packages/language-server/src/common/project.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export async function createProject(context: ProjectContext) {
8585
getPlugins() {
8686
return [
8787
...context.serverConfig?.plugins ?? [],
88-
...context.workspace.workspaces.plugins.map(plugin => plugin.getServicePlugins?.(languageServiceHost, languageService!) ?? []).flat(),
88+
...context.workspace.workspaces.plugins.map(plugin => plugin.getServicePlugins?.(languageServiceHost, languageServiceContext) ?? []).flat(),
8989
];
9090
},
9191
env: {
@@ -105,6 +105,7 @@ export async function createProject(context: ProjectContext) {
105105
},
106106
},
107107
documentRegistry: context.documentRegistry,
108+
getLanguageService: () => languageService!,
108109
});
109110
languageService = embeddedLS.createLanguageService(languageServiceContext);
110111
}

packages/language-server/src/common/workspace.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function createWorkspace(context: WorkspaceContext) {
131131
return findTsconfig(async tsconfig => {
132132
const project = await projects.pathGet(tsconfig);
133133
const ls = project?.getLanguageServiceDontCreate();
134-
const validDoc = ls?.context.pluginContext.typescript?.languageService.getProgram()?.getSourceFile(shared.getPathOfUri(uri.toString()));
134+
const validDoc = ls?.context.typescript?.languageService.getProgram()?.getSourceFile(shared.getPathOfUri(uri.toString()));
135135
return !!validDoc;
136136
});
137137
}

packages/language-server/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { FileSystemProvider } from 'vscode-html-languageservice';
44
import type * as ts from 'typescript/lib/tsserverlibrary';
55
import * as vscode from 'vscode-languageserver';
66
import { URI } from 'vscode-uri';
7+
import { LanguageServiceRuntimeContext } from '@volar/language-service';
78

89
export type FileSystemHost = {
910
ready(connection: vscode.Connection): void,
@@ -54,7 +55,7 @@ export type LanguageServerPlugin<
5455

5556
getServicePlugins?(
5657
host: B,
57-
service: embeddedLS.LanguageService,
58+
context: LanguageServiceRuntimeContext,
5859
): embeddedLS.LanguageServicePlugin[];
5960

6061
onInitialize?(

packages/language-service/src/baseLanguageService.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import * as renamePrepare from './languageFeatures/renamePrepare';
2626
import * as signatureHelp from './languageFeatures/signatureHelp';
2727
import * as diagnostics from './languageFeatures/validation';
2828
import * as workspaceSymbol from './languageFeatures/workspaceSymbols';
29-
import { LanguageServicePlugin, LanguageServicePluginInstance, LanguageServicePluginContext, LanguageServiceRuntimeContext } from './types';
29+
import { LanguageServicePlugin, LanguageServicePluginInstance, LanguageServiceRuntimeContext } from './types';
3030
import type * as ts from 'typescript/lib/tsserverlibrary';
3131

3232
import * as colorPresentations from './documentFeatures/colorPresentations';
@@ -46,8 +46,9 @@ export function createLanguageServiceContext(options: {
4646
host: LanguageServiceHost,
4747
context: ReturnType<typeof createLanguageContext>,
4848
getPlugins(): (LanguageServicePlugin | LanguageServicePluginInstance)[],
49-
env: LanguageServicePluginContext['env'];
49+
env: LanguageServiceRuntimeContext['env'];
5050
documentRegistry: ts.DocumentRegistry | undefined,
51+
getLanguageService: () => LanguageService,
5152
}) {
5253

5354
const ts = options.host.getTypeScriptModule();
@@ -59,37 +60,35 @@ export function createLanguageServiceContext(options: {
5960

6061
let plugins: LanguageServicePluginInstance[] | undefined;
6162

62-
const pluginContext: LanguageServicePluginContext = {
63-
env: options.env,
64-
typescript: ts && tsLs ? {
65-
module: ts,
66-
languageServiceHost: options.context.typescript.languageServiceHost,
67-
languageService: tsLs,
68-
} : undefined,
69-
};
7063
const textDocumentMapper = createDocumentsAndSourceMaps(options.context.virtualFiles);
7164
const documents = new WeakMap<ts.IScriptSnapshot, TextDocument>();
7265
const documentVersions = new Map<string, number>();
7366
const context: LanguageServiceRuntimeContext = {
7467
host: options.host,
7568
core: options.context,
69+
env: options.env,
7670
get plugins() {
7771
if (!plugins) {
72+
plugins = []; // avoid infinite loop
7873
plugins = options.getPlugins().map(plugin => {
7974
if (plugin instanceof Function) {
80-
const _plugin = plugin(pluginContext);
81-
_plugin.setup?.(pluginContext);
75+
const _plugin = plugin(this, options.getLanguageService());
76+
_plugin.setup?.(this);
8277
return _plugin;
8378
}
8479
else {
85-
plugin.setup?.(pluginContext);
80+
plugin.setup?.(this);
8681
return plugin;
8782
}
8883
});
8984
}
9085
return plugins;
9186
},
92-
pluginContext,
87+
typescript: ts && tsLs ? {
88+
module: ts,
89+
languageServiceHost: options.context.typescript.languageServiceHost,
90+
languageService: tsLs,
91+
} : undefined,
9392
documents: textDocumentMapper,
9493
getTextDocument,
9594
};
@@ -162,7 +161,7 @@ export function createLanguageService(context: LanguageServiceRuntimeContext) {
162161
doExecuteCommand: executeCommand.register(context),
163162
getInlayHints: inlayHints.register(context),
164163
callHierarchy: callHierarchy.register(context),
165-
dispose: () => context.pluginContext.typescript?.languageService.dispose(),
164+
dispose: () => context.typescript?.languageService.dispose(),
166165
context,
167166
};
168167
}

packages/language-service/src/documentFeatures/format.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function register(context: LanguageServiceRuntimeContext) {
3333
const originalSnapshot = source[0];
3434
const rootVirtualFile = source[1];
3535
const originalDocument = document;
36-
const initialIndentLanguageId = await context.pluginContext.env.configurationHost?.getConfiguration<Record<string, boolean>>('volar.format.initialIndent') ?? { html: true };
36+
const initialIndentLanguageId = await context.env.configurationHost?.getConfiguration<Record<string, boolean>>('volar.format.initialIndent') ?? { html: true };
3737

3838
let level = 0;
3939
let edited = false;
@@ -229,10 +229,10 @@ export function register(context: LanguageServiceRuntimeContext) {
229229
let edits: vscode.TextEdit[] | null | undefined;
230230
let recover: (() => void) | undefined;
231231

232-
if (formatDocument !== document && isTsDocument(formatDocument) && context.pluginContext.typescript) {
232+
if (formatDocument !== document && isTsDocument(formatDocument) && context.typescript) {
233233
const formatFileName = shared.getPathOfUri(formatDocument.uri);
234234
const formatSnapshot = stringToSnapshot(formatDocument.getText());
235-
const host = context.pluginContext.typescript.languageServiceHost;
235+
const host = context.typescript.languageServiceHost;
236236
const original = {
237237
getProjectVersion: host.getProjectVersion,
238238
getScriptVersion: host.getScriptVersion,

packages/language-service/src/types.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,15 @@ import type * as vscode from 'vscode-languageserver-protocol';
66
import type { TextDocument } from 'vscode-languageserver-textdocument';
77
import { URI } from 'vscode-uri';
88
import { DocumentsAndSourceMaps } from './documents';
9+
import { LanguageService } from '@volar/language-service';
910

1011
export * from 'vscode-languageserver-protocol';
1112

12-
export interface LanguageServiceRuntimeContext {
13-
host: LanguageServiceHost;
13+
export interface LanguageServiceRuntimeContext<Host extends LanguageServiceHost = LanguageServiceHost> {
14+
host: Host;
1415
core: LanguageContext;
1516
documents: DocumentsAndSourceMaps;
1617
plugins: LanguageServicePluginInstance[];
17-
pluginContext: LanguageServicePluginContext;
18-
getTextDocument(uri: string): TextDocument | undefined;
19-
};
20-
21-
export interface LanguageServicePluginContext {
2218
typescript: {
2319
module: typeof import('typescript/lib/tsserverlibrary');
2420
languageServiceHost: ts.LanguageServiceHost;
@@ -30,8 +26,9 @@ export interface LanguageServicePluginContext {
3026
documentContext?: DocumentContext;
3127
fileSystemProvider?: FileSystemProvider;
3228
schemaRequestService?: SchemaRequestService;
33-
},
34-
}
29+
};
30+
getTextDocument(uri: string): TextDocument | undefined;
31+
};
3532

3633
export interface ConfigurationHost {
3734
getConfiguration: (<T> (section: string, scopeUri?: string) => Promise<T | undefined>),
@@ -63,11 +60,11 @@ export interface ExecuteCommandContext {
6360
applyEdit(paramOrEdit: vscode.ApplyWorkspaceEditParams | vscode.WorkspaceEdit): Promise<vscode.ApplyWorkspaceEditResult>;
6461
}
6562

66-
export type LanguageServicePlugin<T = {}> = ((context: LanguageServicePluginContext) => LanguageServicePluginInstance & T);
63+
export type LanguageServicePlugin<T = {}> = ((context: LanguageServiceRuntimeContext, service: LanguageService) => LanguageServicePluginInstance & T);
6764

6865
export interface LanguageServicePluginInstance {
6966

70-
setup?(context: LanguageServicePluginContext): void;
67+
setup?(context: LanguageServiceRuntimeContext): void;
7168

7269
validation?: {
7370
onSemantic?(document: TextDocument): NullableResult<vscode.Diagnostic[]>;

plugins/pug/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ const plugin: LanguageServicePlugin<{
99
updateCustomData(extraData: html.IHTMLDataProvider[]): void,
1010
getPugLs: () => pug.LanguageService,
1111
getPugDocument: (document: TextDocument) => pug.PugDocument | undefined,
12-
}> = (context) => {
12+
}> = (context, service) => {
1313

1414
const pugDocuments = new WeakMap<TextDocument, [number, pug.PugDocument]>();
15-
const htmlPlugin = useHtmlPlugin()(context);
15+
const htmlPlugin = useHtmlPlugin()(context, service);
1616
const pugLs = pug.getLanguageService(htmlPlugin.getHtmlLs());
1717

1818
return {

vue-language-tools/typescript-vue-plugin/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const init: ts.server.PluginModuleFactory = (modules) => {
3737
return info.project.__vue_getScriptKind(fileName);
3838
};
3939

40-
const vueTsLsHost: vue.LanguageServiceHost = {
40+
const vueTsLsHost: vue.VueLanguageServiceHost = {
4141
getNewLine: () => info.project.getNewLine(),
4242
useCaseSensitiveFileNames: () => info.project.useCaseSensitiveFileNames(),
4343
readFile: path => info.project.readFile(path),

vue-language-tools/vue-component-meta/src/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function createComponentMetaCheckerWorker(
7777

7878
const scriptSnapshots = new Map<string, ts.IScriptSnapshot>();
7979
const scriptVersions = new Map<string, number>();
80-
const _host: vue.LanguageServiceHost = {
80+
const _host: vue.VueLanguageServiceHost = {
8181
...ts.sys,
8282
getProjectVersion: () => projectVersion.toString(),
8383
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), // should use ts.getDefaultLibFilePath not ts.getDefaultLibFileName
@@ -126,7 +126,7 @@ function createComponentMetaCheckerWorker(
126126
}
127127

128128
export function baseCreate(
129-
_host: vue.LanguageServiceHost,
129+
_host: vue.VueLanguageServiceHost,
130130
checkerOptions: MetaCheckerOptions,
131131
globalComponentName: string,
132132
ts: typeof import('typescript/lib/tsserverlibrary'),
@@ -136,7 +136,7 @@ export function baseCreate(
136136
*/
137137
const globalComponentSnapshot = ts.ScriptSnapshot.fromString('<script setup lang="ts"></script>');
138138
const metaSnapshots: Record<string, ts.IScriptSnapshot> = {};
139-
const host = new Proxy<Partial<vue.LanguageServiceHost>>({
139+
const host = new Proxy<Partial<vue.VueLanguageServiceHost>>({
140140
getScriptFileNames: () => {
141141
const names = _host.getScriptFileNames();
142142
return [
@@ -167,7 +167,7 @@ export function baseCreate(
167167
}
168168
return _host[prop as keyof typeof _host];
169169
},
170-
}) as vue.LanguageServiceHost;
170+
}) as vue.VueLanguageServiceHost;
171171
const vueLanguageModules = ts ? vue.createLanguageModules(
172172
ts,
173173
host.getCompilationSettings(),

vue-language-tools/vue-language-core/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { VueEmbeddedFile } from './sourceFile';
77

88
export type { SFCParseResult } from '@vue/compiler-sfc';
99

10-
export type LanguageServiceHost = embedded.LanguageServiceHost & {
10+
export type VueLanguageServiceHost = embedded.LanguageServiceHost & {
1111
getVueCompilationSettings(): VueCompilerOptions,
1212
};
1313

0 commit comments

Comments
 (0)