Skip to content

Commit 1e7fe05

Browse files
authored
feat(typescript-plugin): allow triggering file references on <template> (#5734)
1 parent 71115fb commit 1e7fe05

File tree

1 file changed

+79
-14
lines changed

1 file changed

+79
-14
lines changed

packages/typescript-plugin/lib/common.ts

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ export function createVueLanguageServiceProxy<T>(
1414
const proxyCache = new Map<string | symbol, Function | undefined>();
1515
const getProxyMethod = (target: ts.LanguageService, p: string | symbol): Function | undefined => {
1616
switch (p) {
17+
case 'findReferences':
18+
return findReferences(ts, language, languageService, asScriptId, target[p]);
1719
case 'getCompletionsAtPosition':
1820
return getCompletionsAtPosition(ts, language, asScriptId, vueOptions, target[p]);
1921
case 'getCompletionEntryDetails':
2022
return getCompletionEntryDetails(language, target[p]);
2123
case 'getCodeFixesAtPosition':
2224
return getCodeFixesAtPosition(target[p]);
2325
case 'getDefinitionAndBoundSpan':
24-
return getDefinitionAndBoundSpan(language, asScriptId, target[p]);
26+
return getDefinitionAndBoundSpan(ts, language, asScriptId, target[p]);
2527
}
2628
};
2729

@@ -42,6 +44,56 @@ export function createVueLanguageServiceProxy<T>(
4244
});
4345
}
4446

47+
function findReferences<T>(
48+
ts: typeof import('typescript'),
49+
language: Language<T>,
50+
languageService: ts.LanguageService,
51+
asScriptId: (fileName: string) => T,
52+
findReferences: ts.LanguageService['findReferences'],
53+
): ts.LanguageService['findReferences'] {
54+
return (fileName, position) => {
55+
const result = findReferences(fileName, position);
56+
57+
const sourceScript = language.scripts.get(asScriptId(fileName));
58+
const root = sourceScript?.generated?.root;
59+
if (!(root instanceof VueVirtualCode)) {
60+
return result;
61+
}
62+
63+
const { template } = root.sfc;
64+
if (template) {
65+
const textSpan = {
66+
start: template.start + 1,
67+
length: 'template'.length,
68+
};
69+
if (position >= textSpan.start && position <= textSpan.start + textSpan.length) {
70+
result?.push({
71+
definition: {
72+
fileName,
73+
textSpan,
74+
kind: ts.ScriptElementKind.scriptElement,
75+
name: fileName,
76+
containerKind: ts.ScriptElementKind.unknown,
77+
containerName: '',
78+
displayParts: [],
79+
},
80+
references: [
81+
{
82+
fileName,
83+
textSpan,
84+
isDefinition: true,
85+
isWriteAccess: false,
86+
},
87+
...languageService.getFileReferences(fileName),
88+
],
89+
});
90+
}
91+
}
92+
93+
return result;
94+
};
95+
}
96+
4597
function getCompletionsAtPosition<T>(
4698
ts: typeof import('typescript'),
4799
language: Language<T>,
@@ -190,24 +242,42 @@ function getCodeFixesAtPosition(
190242
}
191243

192244
function getDefinitionAndBoundSpan<T>(
245+
ts: typeof import('typescript'),
193246
language: Language<T>,
194247
asScriptId: (fileName: string) => T,
195248
getDefinitionAndBoundSpan: ts.LanguageService['getDefinitionAndBoundSpan'],
196249
): ts.LanguageService['getDefinitionAndBoundSpan'] {
197250
return (fileName, position) => {
198251
const result = getDefinitionAndBoundSpan(fileName, position);
199-
if (!result?.definitions?.length) {
200-
return result;
201-
}
202252

203253
const sourceScript = language.scripts.get(asScriptId(fileName));
204-
if (!sourceScript?.generated) {
254+
const root = sourceScript?.generated?.root;
255+
if (!(root instanceof VueVirtualCode)) {
205256
return result;
206257
}
207258

208-
const root = sourceScript.generated.root;
209-
if (!(root instanceof VueVirtualCode)) {
210-
return result;
259+
if (!result?.definitions?.length) {
260+
const { template } = root.sfc;
261+
if (template) {
262+
const textSpan = {
263+
start: template.start + 1,
264+
length: 'template'.length,
265+
};
266+
if (position >= textSpan.start && position <= textSpan.start + textSpan.length) {
267+
return {
268+
textSpan,
269+
definitions: [{
270+
fileName,
271+
textSpan,
272+
kind: ts.ScriptElementKind.scriptElement,
273+
name: fileName,
274+
containerKind: ts.ScriptElementKind.unknown,
275+
containerName: '',
276+
}],
277+
};
278+
}
279+
}
280+
return;
211281
}
212282

213283
if (
@@ -219,7 +289,6 @@ function getDefinitionAndBoundSpan<T>(
219289
}
220290

221291
const definitions = new Set<ts.DefinitionInfo>(result.definitions);
222-
const skippedDefinitions: ts.DefinitionInfo[] = [];
223292

224293
// #5275
225294
if (result.definitions.length >= 2) {
@@ -228,15 +297,11 @@ function getDefinitionAndBoundSpan<T>(
228297
root.sfc.content[definition.textSpan.start - 1] === '@'
229298
|| root.sfc.content.slice(definition.textSpan.start - 5, definition.textSpan.start) === 'v-on:'
230299
) {
231-
skippedDefinitions.push(definition);
300+
definitions.delete(definition);
232301
}
233302
}
234303
}
235304

236-
for (const definition of skippedDefinitions) {
237-
definitions.delete(definition);
238-
}
239-
240305
return {
241306
definitions: [...definitions],
242307
textSpan: result.textSpan,

0 commit comments

Comments
 (0)