5
5
6
6
"github.com/microsoft/typescript-go/internal/ast"
7
7
"github.com/microsoft/typescript-go/internal/astnav"
8
+ "github.com/microsoft/typescript-go/internal/checker"
8
9
"github.com/microsoft/typescript-go/internal/core"
9
10
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
10
11
"github.com/microsoft/typescript-go/internal/scanner"
@@ -20,24 +21,69 @@ func (l *LanguageService) ProvideDefinition(ctx context.Context, documentURI lsp
20
21
checker , done := program .GetTypeCheckerForFile (ctx , file )
21
22
defer done ()
22
23
24
+ calledDeclaration := tryGetSignatureDeclaration (checker , node )
25
+ if calledDeclaration != nil {
26
+ name := ast .GetNameOfDeclaration (calledDeclaration )
27
+ if name != nil {
28
+ return l .createLocationsFromDeclarations ([]* ast.Node {name })
29
+ }
30
+ }
31
+
23
32
if symbol := checker .GetSymbolAtLocation (node ); symbol != nil {
24
33
if symbol .Flags & ast .SymbolFlagsAlias != 0 {
25
34
if resolved , ok := checker .ResolveAlias (symbol ); ok {
26
35
symbol = resolved
27
36
}
28
37
}
29
38
30
- locations := make ([]lsproto.Location , 0 , len (symbol .Declarations ))
31
- for _ , decl := range symbol .Declarations {
32
- file := ast .GetSourceFileOfNode (decl )
33
- loc := decl .Loc
34
- pos := scanner .GetTokenPosOfNode (decl , file , false /*includeJSDoc*/ )
35
- locations = append (locations , lsproto.Location {
36
- Uri : FileNameToDocumentURI (file .FileName ()),
37
- Range : l .converters .ToLSPRange (file , core .NewTextRange (pos , loc .End ())),
38
- })
39
- }
40
- return & lsproto.Definition {Locations : & locations }, nil
39
+ return l .createLocationsFromDeclarations (symbol .Declarations )
41
40
}
42
41
return nil , nil
43
42
}
43
+
44
+ func (l * LanguageService ) createLocationsFromDeclarations (declarations []* ast.Node ) (* lsproto.Definition , error ) {
45
+ locations := make ([]lsproto.Location , 0 , len (declarations ))
46
+ for _ , decl := range declarations {
47
+ file := ast .GetSourceFileOfNode (decl )
48
+ loc := decl .Loc
49
+ pos := scanner .GetTokenPosOfNode (decl , file , false /*includeJSDoc*/ )
50
+ locations = append (locations , lsproto.Location {
51
+ Uri : FileNameToDocumentURI (file .FileName ()),
52
+ Range : l .converters .ToLSPRange (file , core .NewTextRange (pos , loc .End ())),
53
+ })
54
+ }
55
+ return & lsproto.Definition {Locations : & locations }, nil
56
+ }
57
+
58
+ /** Returns a CallLikeExpression where `node` is the target being invoked. */
59
+ func getAncestorCallLikeExpression (node * ast.Node ) * ast.Node {
60
+ target := ast .FindAncestor (node , func (n * ast.Node ) bool {
61
+ return ! isRightSideOfPropertyAccess (n )
62
+ })
63
+
64
+ callLike := target .Parent
65
+ if callLike != nil && ast .IsCallLikeExpression (callLike ) && ast .GetInvokedExpression (callLike ) == target {
66
+ return callLike
67
+ }
68
+
69
+ return nil
70
+ }
71
+
72
+ func tryGetSignatureDeclaration (typeChecker * checker.Checker , node * ast.Node ) * ast.Node {
73
+ var signature * checker.Signature
74
+ callLike := getAncestorCallLikeExpression (node )
75
+ if callLike != nil {
76
+ signature = typeChecker .GetResolvedSignature (callLike )
77
+ }
78
+
79
+ // Don't go to a function type, go to the value having that type.
80
+ var declaration * ast.Node
81
+ if signature != nil && signature .Declaration () != nil {
82
+ declaration = signature .Declaration ()
83
+ if ast .IsFunctionLike (declaration ) && ! ast .IsFunctionTypeNode (declaration ) {
84
+ return declaration
85
+ }
86
+ }
87
+
88
+ return nil
89
+ }
0 commit comments