Skip to content

Commit 493c2c2

Browse files
committed
fix(enableFileDefinitions): lookup from workspace root file even on relative path
1 parent 62fb8e8 commit 493c2c2

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

typescript/src/definitions.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,42 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
2020
})
2121
}
2222

23+
const program = languageService.getProgram()!
24+
const sourceFile = program.getSourceFile(fileName)!
25+
const getNode = () => {
26+
return findChildContainingExactPosition(sourceFile, position)
27+
}
28+
29+
const noDefs = !prior || !prior.definitions || prior.definitions.length === 0
30+
const tryFileResolve = noDefs || ['?', '#'].some(x => prior.definitions?.[0]?.fileName?.includes(x))
31+
2332
// Definition fallbacks
24-
if (!prior || prior.definitions?.length === 0) {
25-
const program = languageService.getProgram()!
26-
const sourceFile = program.getSourceFile(fileName)!
27-
const node = findChildContainingExactPosition(sourceFile, position)
33+
if (noDefs || tryFileResolve) {
34+
const node = getNode()
2835
if (node && ts.isStringLiteral(node)) {
2936
const textSpanStart = node.pos + node.getLeadingTriviaWidth() + 1 // + 1 for quote
3037
const textSpan = {
3138
start: textSpanStart,
3239
length: node.end - textSpanStart - 1,
3340
}
34-
if (c('enableFileDefinitions') && ['./', '../'].some(str => node.text.startsWith(str))) {
35-
const file = join(fileName, '..', node.text)
36-
if (languageServiceHost.fileExists?.(file)) {
41+
42+
if (tryFileResolve && c('enableFileDefinitions') && ['./', '../'].some(str => node.text.startsWith(str))) {
43+
const pathText = node.text.split('?')[0]!.split('#')[0]!
44+
const fileCandidates = [
45+
join(fileName, '..', pathText),
46+
// also try to resolve from root. Why? It might common in Node.js script paths that go from working directory (project root)
47+
pathText.startsWith('./') ? join(languageServiceHost.getCurrentDirectory(), pathText) : (undefined as never),
48+
].filter(Boolean)
49+
const resolvedFile = fileCandidates.find(file => languageServiceHost.fileExists?.(file))
50+
if (resolvedFile) {
3751
return {
3852
textSpan,
3953
definitions: [
4054
{
4155
containerKind: undefined as any,
4256
containerName: '',
4357
name: '',
44-
fileName: file,
58+
fileName: resolvedFile,
4559
textSpan: { start: 0, length: 0 },
4660
kind: ts.ScriptElementKind.moduleElement,
4761
contextSpan: { start: 0, length: 0 },
@@ -50,10 +64,9 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
5064
}
5165
}
5266
}
53-
5467
// partial fix for https://github.com/microsoft/TypeScript/issues/49033 (string literal in function call definition)
5568
// thoughts about type definition: no impl here, will be simpler to do this in core instead
56-
if (ts.isCallExpression(node.parent)) {
69+
if (noDefs && ts.isCallExpression(node.parent)) {
5770
const parameterIndex = node.parent.arguments.indexOf(node)
5871
const typeChecker = program.getTypeChecker()
5972
const type = typeChecker.getContextualType(node.parent.expression) ?? typeChecker.getTypeAtLocation(node.parent.expression)
@@ -108,7 +121,8 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
108121
}
109122
}
110123
}
111-
return prior
124+
125+
if (noDefs) return prior
112126
}
113127

114128
if (__WEB__) {

0 commit comments

Comments
 (0)