@@ -20,28 +20,42 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
20
20
} )
21
21
}
22
22
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
+
23
32
// 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 ( )
28
35
if ( node && ts . isStringLiteral ( node ) ) {
29
36
const textSpanStart = node . pos + node . getLeadingTriviaWidth ( ) + 1 // + 1 for quote
30
37
const textSpan = {
31
38
start : textSpanStart ,
32
39
length : node . end - textSpanStart - 1 ,
33
40
}
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 ) {
37
51
return {
38
52
textSpan,
39
53
definitions : [
40
54
{
41
55
containerKind : undefined as any ,
42
56
containerName : '' ,
43
57
name : '' ,
44
- fileName : file ,
58
+ fileName : resolvedFile ,
45
59
textSpan : { start : 0 , length : 0 } ,
46
60
kind : ts . ScriptElementKind . moduleElement ,
47
61
contextSpan : { start : 0 , length : 0 } ,
@@ -50,10 +64,9 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
50
64
}
51
65
}
52
66
}
53
-
54
67
// partial fix for https://github.com/microsoft/TypeScript/issues/49033 (string literal in function call definition)
55
68
// 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 ) ) {
57
70
const parameterIndex = node . parent . arguments . indexOf ( node )
58
71
const typeChecker = program . getTypeChecker ( )
59
72
const type = typeChecker . getContextualType ( node . parent . expression ) ?? typeChecker . getTypeAtLocation ( node . parent . expression )
@@ -108,7 +121,8 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
108
121
}
109
122
}
110
123
}
111
- return prior
124
+
125
+ if ( noDefs ) return prior
112
126
}
113
127
114
128
if ( __WEB__ ) {
0 commit comments