Skip to content

Commit 2e1108c

Browse files
committed
1 parent 452a51f commit 2e1108c

File tree

28 files changed

+222
-147
lines changed

28 files changed

+222
-147
lines changed

extensions/vscode-vue-language-features/src/browserClientMain.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export function activate(context: vscode.ExtensionContext) {
77
return commonActivate(context, async (
88
id,
99
name,
10-
documentSelector,
10+
langs,
1111
initOptions,
1212
fillInitializeParams,
1313
) => {
@@ -21,7 +21,7 @@ export function activate(context: vscode.ExtensionContext) {
2121
const serverMain = vscode.Uri.joinPath(context.extensionUri, 'dist/browser/server.js');
2222
const worker = new Worker(serverMain.toString());
2323
const clientOptions: lsp.LanguageClientOptions = {
24-
documentSelector,
24+
documentSelector: langs.map<lsp.DocumentFilter>(lang => ({ language: lang })),
2525
initializationOptions: initOptions,
2626
progressOnInitialization: true,
2727
synchronize: {

extensions/vscode-vue-language-features/src/common.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ let client_syntactic: lsp.BaseLanguageClient;
2929
type CreateLanguageClient = (
3030
id: string,
3131
name: string,
32-
documentSelector: lsp.DocumentSelector,
32+
langs: string[],
3333
initOptions: VueServerInitializationOptions,
3434
fillInitializeParams: (params: lsp.InitializeParams) => void,
3535
port: number,
@@ -190,28 +190,27 @@ export function takeOverModeEnabled() {
190190
return false;
191191
}
192192

193-
function getDocumentSelector(serverMode: ServerMode) {
193+
export function getDocumentSelector(serverMode: ServerMode) {
194194
const takeOverMode = takeOverModeEnabled();
195-
const selector: lsp.DocumentSelector = takeOverMode ?
196-
[
197-
{ language: 'vue' },
198-
{ language: 'javascript' },
199-
{ language: 'typescript' },
200-
{ language: 'javascriptreact' },
201-
{ language: 'typescriptreact' },
202-
] : [
203-
{ language: 'vue' },
204-
];
195+
const langs = takeOverMode ? [
196+
'vue',
197+
'javascript',
198+
'typescript',
199+
'javascriptreact',
200+
'typescriptreact',
201+
] : [
202+
'vue',
203+
];
205204
if (takeOverMode && serverMode === ServerMode.Semantic) {
206-
selector.push({ language: 'json' });
205+
langs.push('json');
207206
}
208207
if (processHtml()) {
209-
selector.push({ language: 'html' });
208+
langs.push('html');
210209
}
211210
if (processMd()) {
212-
selector.push({ language: 'markdown' });
211+
langs.push('markdown');
213212
}
214-
return selector;
213+
return langs;
215214
}
216215

217216
function useSecondServer() {

extensions/vscode-vue-language-features/src/nodeClientMain.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
1+
import { ServerMode } from '@volar/vue-language-server';
2+
import * as fs from 'fs';
3+
import * as os from 'os';
4+
import * as path from 'path';
15
import * as vscode from 'vscode';
26
import * as lsp from 'vscode-languageclient/node';
3-
import { activate as commonActivate, deactivate as commonDeactivate } from './common';
7+
import { activate as commonActivate, deactivate as commonDeactivate, getDocumentSelector } from './common';
48
import { middleware } from './middleware';
59

610
export function activate(context: vscode.ExtensionContext) {
11+
12+
const cancellationPipeName = path.join(os.tmpdir(), `vscode-${context.extension.id}-cancellation-pipe.tmp`);
13+
const langs = getDocumentSelector(ServerMode.Semantic);
14+
15+
vscode.workspace.onDidChangeTextDocument((e) => {
16+
if (langs.includes(e.document.languageId)) {
17+
fs.writeFileSync(cancellationPipeName, e.document.uri.fsPath + '|' + e.document.version);
18+
}
19+
});
20+
721
return commonActivate(context, async (
822
id,
923
name,
10-
documentSelector,
24+
langs,
1125
initOptions,
1226
fillInitializeParams,
1327
port,
1428
) => {
1529

30+
initOptions.cancellationPipeName = cancellationPipeName;
31+
1632
class _LanguageClient extends lsp.LanguageClient {
1733
fillInitializeParams(params: lsp.InitializeParams) {
1834
fillInitializeParams(params);
@@ -40,7 +56,7 @@ export function activate(context: vscode.ExtensionContext) {
4056
};
4157
const clientOptions: lsp.LanguageClientOptions = {
4258
middleware,
43-
documentSelector,
59+
documentSelector: langs.map<lsp.DocumentFilter>(lang => ({ language: lang })),
4460
initializationOptions: initOptions,
4561
progressOnInitialization: true,
4662
synchronize: {

packages/language-server/src/features/customFeatures.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function register(
5353
if (progress.token.isCancellationRequested) {
5454
continue;
5555
}
56-
let _result = await ls.doValidation(vueFile.uri);
56+
let _result = await ls.doValidation(vueFile.uri, progress.token);
5757
connection.sendDiagnostics({ uri: vueFile.uri, diagnostics: _result });
5858
errors += _result.filter(error => error.severity === vscode.DiagnosticSeverity.Error).length;
5959
warnings += _result.filter(error => error.severity === vscode.DiagnosticSeverity.Warning).length;

packages/language-server/src/features/languageFeatures.ts

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import * as embedded from '@volar/language-service';
22
import * as vscode from 'vscode-languageserver';
33
import { AutoInsertRequest, FindFileReferenceRequest, ShowReferencesNotification } from '../protocol';
4+
import { CancellactionTokenHost } from '../utils/cancellationPipe';
45
import type { Workspaces } from '../utils/workspaces';
6+
import * as shared from '@volar/shared';
57

68
export function register(
79
connection: vscode.Connection,
810
projects: Workspaces,
911
initParams: vscode.InitializeParams,
12+
cancelHost: CancellactionTokenHost,
1013
) {
1114

1215
let lastCompleteUri: string;
@@ -15,7 +18,7 @@ export function register(
1518
let lastCodeActionLs: embedded.LanguageService;
1619
let lastCallHierarchyLs: embedded.LanguageService;
1720

18-
connection.onCompletion(async params => {
21+
connection.onCompletion(async (params) => {
1922
return worker(params.textDocument.uri, async vueLs => {
2023
lastCompleteUri = params.textDocument.uri;
2124
lastCompleteLs = vueLs;
@@ -32,44 +35,43 @@ export function register(
3235
return list;
3336
});
3437
});
35-
connection.onCompletionResolve(async item => {
38+
connection.onCompletionResolve(async (item) => {
3639
if (lastCompleteUri && lastCompleteLs) {
3740
item = await lastCompleteLs.doCompletionResolve(item);
3841
fixTextEdit(item);
3942
}
4043
return item;
4144
});
42-
connection.onHover(async params => {
45+
connection.onHover(async (params) => {
4346
return worker(params.textDocument.uri, vueLs => {
4447
return vueLs.doHover(params.textDocument.uri, params.position);
4548
});
4649
});
47-
connection.onSignatureHelp(async params => {
50+
connection.onSignatureHelp(async (params) => {
4851
return worker(params.textDocument.uri, vueLs => {
4952
return vueLs.getSignatureHelp(params.textDocument.uri, params.position, params.context);
5053
});
5154
});
52-
connection.onPrepareRename(async params => {
55+
connection.onPrepareRename(async (params) => {
5356
return worker(params.textDocument.uri, vueLs => {
5457
return vueLs.prepareRename(params.textDocument.uri, params.position);
5558
});
5659
});
57-
connection.onRenameRequest(async params => {
60+
connection.onRenameRequest(async (params) => {
5861
return worker(params.textDocument.uri, vueLs => {
5962
return vueLs.doRename(params.textDocument.uri, params.position, params.newName);
6063
});
6164
});
62-
connection.onCodeLens(async params => {
65+
connection.onCodeLens(async (params) => {
6366
return worker(params.textDocument.uri, async vueLs => {
6467
lastCodeLensLs = vueLs;
6568
return vueLs.doCodeLens(params.textDocument.uri);
6669
});
6770
});
68-
connection.onCodeLensResolve(async codeLens => {
71+
connection.onCodeLensResolve(async (codeLens) => {
6972
return await lastCodeLensLs?.doCodeLensResolve(codeLens) ?? codeLens;
7073
});
7174
connection.onExecuteCommand(async (params, token, workDoneProgress) => {
72-
7375
if (params.command === embedded.executePluginCommand) {
7476

7577
const args = params.arguments as embedded.ExecutePluginCommandArgs | undefined;
@@ -87,7 +89,7 @@ export function register(
8789
});
8890
}
8991
});
90-
connection.onCodeAction(async params => {
92+
connection.onCodeAction(async (params) => {
9193
return worker(params.textDocument.uri, async vueLs => {
9294
lastCodeActionLs = vueLs;
9395
let codeActions = await vueLs.doCodeActions(params.textDocument.uri, params.range, params.context) ?? [];
@@ -105,46 +107,47 @@ export function register(
105107
return codeActions;
106108
});
107109
});
108-
connection.onCodeActionResolve(async codeAction => {
110+
connection.onCodeActionResolve(async (codeAction) => {
109111
return await lastCodeActionLs.doCodeActionResolve(codeAction) ?? codeAction;
110112
});
111-
connection.onReferences(async params => {
113+
connection.onReferences(async (params) => {
112114
return worker(params.textDocument.uri, vueLs => {
113115
return vueLs.findReferences(params.textDocument.uri, params.position);
114116
});
115117
});
116-
connection.onRequest(FindFileReferenceRequest.type, async params => {
118+
connection.onRequest(FindFileReferenceRequest.type, async (params) => {
117119
return worker(params.textDocument.uri, vueLs => {
118120
return vueLs.findFileReferences(params.textDocument.uri);
119121
});
120122
});
121-
connection.onImplementation(async params => {
123+
connection.onImplementation(async (params) => {
122124
return worker(params.textDocument.uri, vueLs => {
123125
return vueLs.findImplementations(params.textDocument.uri, params.position);
124126
});
125127
});
126-
connection.onDefinition(async params => {
128+
connection.onDefinition(async (params) => {
127129
return worker(params.textDocument.uri, vueLs => {
128130
return vueLs.findDefinition(params.textDocument.uri, params.position);
129131
});
130132
});
131-
connection.onTypeDefinition(async params => {
133+
connection.onTypeDefinition(async (params) => {
132134
return worker(params.textDocument.uri, vueLs => {
133135
return vueLs.findTypeDefinition(params.textDocument.uri, params.position);
134136
});
135137
});
136-
connection.onDocumentHighlight(async params => {
138+
connection.onDocumentHighlight(async (params) => {
137139
return worker(params.textDocument.uri, vueLs => {
138140
return vueLs.findDocumentHighlights(params.textDocument.uri, params.position);
139141
});
140142
});
141-
connection.onDocumentLinks(async params => {
143+
connection.onDocumentLinks(async (params) => {
142144
return worker(params.textDocument.uri, vueLs => {
143145
return vueLs.findDocumentLinks(params.textDocument.uri);
144146
});
145147
});
146148
connection.onWorkspaceSymbol(async (params, token) => {
147149

150+
148151
let results: vscode.SymbolInformation[] = [];
149152

150153
for (const _workspace of projects.workspaces.values()) {
@@ -164,19 +167,21 @@ export function register(
164167

165168
return results;
166169
});
167-
connection.languages.callHierarchy.onPrepare(async params => {
170+
connection.languages.callHierarchy.onPrepare(async (params) => {
168171
return await worker(params.textDocument.uri, async vueLs => {
169172
lastCallHierarchyLs = vueLs;
170173
return vueLs.callHierarchy.doPrepare(params.textDocument.uri, params.position);
171174
}) ?? [];
172175
});
173-
connection.languages.callHierarchy.onIncomingCalls(async params => {
176+
connection.languages.callHierarchy.onIncomingCalls(async (params) => {
174177
return await lastCallHierarchyLs?.callHierarchy.getIncomingCalls(params.item) ?? [];
175178
});
176-
connection.languages.callHierarchy.onOutgoingCalls(async params => {
179+
connection.languages.callHierarchy.onOutgoingCalls(async (params) => {
177180
return await lastCallHierarchyLs?.callHierarchy.getOutgoingCalls(params.item) ?? [];
178181
});
179182
connection.languages.semanticTokens.on(async (params, token, _, resultProgress) => {
183+
await shared.sleep(200);
184+
if (token.isCancellationRequested) return buildTokens([]);
180185
return await worker(params.textDocument.uri, async vueLs => {
181186

182187
const result = await vueLs?.getSemanticTokens(
@@ -190,6 +195,8 @@ export function register(
190195
}) ?? buildTokens([]);
191196
});
192197
connection.languages.semanticTokens.onRange(async (params, token, _, resultProgress) => {
198+
await shared.sleep(200);
199+
if (token.isCancellationRequested) return buildTokens([]);
193200
return await worker(params.textDocument.uri, async vueLs => {
194201

195202
const result = await vueLs?.getSemanticTokens(
@@ -202,9 +209,10 @@ export function register(
202209
return buildTokens(result);
203210
}) ?? buildTokens([]);
204211
});
205-
connection.languages.diagnostics.on(async (params, cancellationToken, workDoneProgressReporter, resultProgressReporter) => {
212+
connection.languages.diagnostics.on(async (params, token, workDoneProgressReporter, resultProgressReporter) => {
213+
token = cancelHost.createCancellactionToken(token);
206214
const result = await worker(params.textDocument.uri, vueLs => {
207-
return vueLs.doValidation(params.textDocument.uri, errors => {
215+
return vueLs.doValidation(params.textDocument.uri, token, errors => {
208216
// resultProgressReporter is undefined in vscode
209217
resultProgressReporter?.report({
210218
relatedDocuments: {
@@ -214,15 +222,15 @@ export function register(
214222
},
215223
},
216224
});
217-
}, cancellationToken);
225+
});
218226
});
219227
return {
220228
kind: vscode.DocumentDiagnosticReportKind.Full,
221229
items: result ?? [],
222230
};
223231
});
224232
connection.languages.inlayHint.on(async params => {
225-
return worker(params.textDocument.uri, vueLs => {
233+
return worker(params.textDocument.uri, async vueLs => {
226234
return vueLs.getInlayHints(params.textDocument.uri, params.range);
227235
});
228236
});
@@ -253,7 +261,12 @@ export function register(
253261
async function worker<T>(uri: string, cb: (vueLs: embedded.LanguageService) => T) {
254262
const vueLs = await getLanguageService(uri);
255263
if (vueLs) {
256-
return cb(vueLs);
264+
try {
265+
return cb(vueLs); // handle for TS cancel throw
266+
}
267+
catch {
268+
return undefined;
269+
}
257270
}
258271
}
259272
function buildTokens(tokens: embedded.SemanticToken[]) {

packages/language-server/src/server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createDocumentServiceHost } from './utils/documentServiceHost';
66
import { createSnapshots } from './utils/snapshots';
77
import { createWorkspaces } from './utils/workspaces';
88
import { setupSemanticCapabilities, setupSyntacticCapabilities } from './registerFeatures';
9+
import { createCancellactionTokenHost } from './utils/cancellationPipe';
910

1011
export function createCommonLanguageServer(
1112
connection: vscode.Connection,
@@ -123,6 +124,7 @@ export function createCommonLanguageServer(
123124
fsHost = runtimeEnv.createFileSystemHost(ts, params.capabilities);
124125

125126
const tsLocalized = params.locale ? runtimeEnv.loadTypescriptLocalized(options.typescript.tsdk, params.locale) : undefined;
127+
const cancelTokenHost = createCancellactionTokenHost(options.cancellationPipeName);
126128
const _projects = createWorkspaces(
127129
runtimeEnv,
128130
plugins,
@@ -134,6 +136,7 @@ export function createCommonLanguageServer(
134136
options,
135137
documents,
136138
connection,
139+
cancelTokenHost,
137140
);
138141
projects = _projects;
139142

@@ -142,7 +145,7 @@ export function createCommonLanguageServer(
142145
}
143146

144147
(await import('./features/customFeatures')).register(connection, projects);
145-
(await import('./features/languageFeatures')).register(connection, projects, params);
148+
(await import('./features/languageFeatures')).register(connection, projects, params, cancelTokenHost);
146149

147150
for (const plugin of plugins) {
148151
plugin.languageService?.onInitialize?.(connection, getLanguageService as any);

packages/language-server/src/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,9 @@ export interface LanguageServerInitializationOptions {
108108
diagnosticModel?: DiagnosticModel;
109109
textDocumentSync?: vscode.TextDocumentSyncKind | number;
110110
// for resolve https://github.com/sublimelsp/LSP-volar/issues/114
111-
ignoreTriggerCharacters?: string[],
111+
ignoreTriggerCharacters?: string[];
112+
/**
113+
* https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29#cancellation
114+
*/
115+
cancellationPipeName?: string;
112116
}

0 commit comments

Comments
 (0)