/
vue-twoslash-queries.ts
70 lines (56 loc) · 2.09 KB
/
vue-twoslash-queries.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { FileKind, forEachEmbeddedFile, LanguageServicePlugin } from '@volar/language-service';
import * as vue from '@volar/vue-language-core';
import * as vscode from 'vscode-languageserver-protocol';
const plugin: LanguageServicePlugin = (context) => {
if (!context.typescript)
return {};
const _ts = context.typescript;
return {
inlayHints: {
on(document, range) {
return worker(document.uri, (vueFile) => {
const hoverOffsets: [vscode.Position, number][] = [];
const inlayHints: vscode.InlayHint[] = [];
for (const pointer of document.getText(range).matchAll(/<!--\s*\^\?\s*-->/g)) {
const offset = pointer.index! + pointer[0].indexOf('^?') + document.offsetAt(range.start);
const position = document.positionAt(offset);
hoverOffsets.push([position, document.offsetAt({
line: position.line - 1,
character: position.character,
})]);
}
forEachEmbeddedFile(vueFile, (embedded) => {
if (embedded.kind === FileKind.TypeScriptHostFile) {
for (const [_, map] of context.documents.getMapsByVirtualFileUri(document.uri)) {
for (const [pointerPosition, hoverOffset] of hoverOffsets) {
for (const [tsOffset, mapping] of map.map.toGeneratedOffsets(hoverOffset)) {
if (mapping.data.hover) {
const quickInfo = _ts.languageService.getQuickInfoAtPosition(embedded.fileName, tsOffset);
if (quickInfo) {
inlayHints.push({
position: { line: pointerPosition.line, character: pointerPosition.character + 2 },
label: _ts.module.displayPartsToString(quickInfo.displayParts),
paddingLeft: true,
paddingRight: false,
});
}
break;
}
}
}
}
}
});
return inlayHints;
});
},
},
};
function worker<T>(uri: string, callback: (vueSourceFile: vue.VueFile) => T) {
const [virtualFile] = context.documents.getVirtualFileByUri(uri);
if (!(virtualFile instanceof vue.VueFile))
return;
return callback(virtualFile);
}
};
export default () => plugin;