Skip to content

Commit e6cf377

Browse files
refactor(language-server): parsing interpolations in extension client (#5633)
1 parent b8cb0ac commit e6cf377

File tree

3 files changed

+71
-35
lines changed

3 files changed

+71
-35
lines changed

extensions/vscode/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from 'reactive-vscode';
1717
import * as vscode from 'vscode';
1818
import { config } from './lib/config';
19+
import * as interpolationDecorators from './lib/interpolationDecorators';
1920
import * as reactivityVisualization from './lib/reactivityVisualization';
2021
import * as welcome from './lib/welcome';
2122

@@ -100,6 +101,7 @@ export = defineExtension(() => {
100101
activateAutoInsertion(selectors, client);
101102
activateDocumentDropEdit(selectors, client);
102103

104+
interpolationDecorators.activate(context, selectors, client);
103105
reactivityVisualization.activate(context, selectors);
104106
welcome.activate(context);
105107
}, { immediate: true });
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { BaseLanguageClient } from '@volar/vscode';
2+
import * as vscode from 'vscode';
3+
import { config } from './config';
4+
5+
const decorationType = vscode.window.createTextEditorDecorationType({
6+
borderWidth: '1px',
7+
borderStyle: 'solid',
8+
borderColor: 'rgba(128, 128, 128, 0.5)',
9+
backgroundColor: 'rgba(200, 200, 200, 0.1)',
10+
borderRadius: '4px',
11+
});
12+
13+
export async function activate(
14+
context: vscode.ExtensionContext,
15+
selector: vscode.DocumentSelector,
16+
client: BaseLanguageClient,
17+
) {
18+
await client.start();
19+
20+
let timeout: ReturnType<typeof setTimeout> | undefined;
21+
22+
for (const editor of vscode.window.visibleTextEditors) {
23+
updateDecorations(editor);
24+
}
25+
26+
context.subscriptions.push(
27+
vscode.window.onDidChangeActiveTextEditor(editor => {
28+
if (editor) {
29+
updateDecorations(editor);
30+
}
31+
}),
32+
vscode.workspace.onDidChangeTextDocument(() => {
33+
const editor = vscode.window.activeTextEditor;
34+
if (editor) {
35+
clearTimeout(timeout);
36+
timeout = setTimeout(() => updateDecorations(editor), 100);
37+
}
38+
}),
39+
vscode.workspace.onDidChangeConfiguration(e => {
40+
if (e.affectsConfiguration('vue.editor.templateInterpolationDecorators')) {
41+
for (const editor of vscode.window.visibleTextEditors) {
42+
updateDecorations(editor);
43+
}
44+
}
45+
}),
46+
);
47+
48+
function updateDecorations(editor: vscode.TextEditor) {
49+
if (!vscode.languages.match(selector, editor.document)) {
50+
return;
51+
}
52+
if (!config.editor.templateInterpolationDecorators) {
53+
editor.setDecorations(decorationType, []);
54+
return;
55+
}
56+
editor.setDecorations(
57+
decorationType,
58+
[...editor.document.getText().matchAll(/{{[\s\S]*?}}/g)].map(match => {
59+
const start = match.index + 2;
60+
const end = match.index + match[0].length - 2;
61+
return new vscode.Range(
62+
editor.document.positionAt(start),
63+
editor.document.positionAt(end),
64+
);
65+
}),
66+
);
67+
}
68+
}

packages/language-server/index.ts

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import type { LanguageServer, TextDocumentIdentifier } from '@volar/language-server';
1+
import type { LanguageServer } from '@volar/language-server';
22
import { createLanguageServiceEnvironment } from '@volar/language-server/lib/project/simpleProject';
33
import { createConnection, createServer } from '@volar/language-server/node';
44
import {
55
createLanguage,
66
createParsedCommandLine,
77
createParsedCommandLineByJson,
88
createVueLanguagePlugin,
9-
forEachEmbeddedCode,
109
} from '@vue/language-core';
1110
import {
1211
createLanguageService,
@@ -210,36 +209,3 @@ connection.onInitialize(params => {
210209
connection.onInitialized(server.initialized);
211210

212211
connection.onShutdown(server.shutdown);
213-
214-
connection.onRequest('vue/interpolationRanges', async (params: {
215-
textDocument: TextDocumentIdentifier;
216-
}): Promise<[number, number][]> => {
217-
const uri = URI.parse(params.textDocument.uri);
218-
const languageService = await server.project.getLanguageService(uri);
219-
const sourceFile = languageService.context.language.scripts.get(uri);
220-
if (sourceFile?.generated) {
221-
const ranges: [number, number][] = [];
222-
for (const code of forEachEmbeddedCode(sourceFile.generated.root)) {
223-
const codeText = code.snapshot.getText(0, code.snapshot.getLength());
224-
if (
225-
(
226-
code.id.startsWith('template_inline_ts_')
227-
&& codeText.startsWith('0 +')
228-
&& codeText.endsWith('+ 0;')
229-
)
230-
|| (code.id.startsWith('style_') && code.id.endsWith('_inline_ts'))
231-
) {
232-
for (const mapping of code.mappings) {
233-
for (let i = 0; i < mapping.sourceOffsets.length; i++) {
234-
ranges.push([
235-
mapping.sourceOffsets[i]!,
236-
mapping.sourceOffsets[i]! + mapping.lengths[i]!,
237-
]);
238-
}
239-
}
240-
}
241-
}
242-
return ranges;
243-
}
244-
return [];
245-
});

0 commit comments

Comments
 (0)