-
Notifications
You must be signed in to change notification settings - Fork 582
/
Copy pathdefinition.go
85 lines (72 loc) · 2.53 KB
/
definition.go
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package ls
import (
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/astnav"
"github.com/microsoft/typescript-go/internal/checker"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/scanner"
)
func (l *LanguageService) ProvideDefinitions(fileName string, position int) []Location {
program, file := l.getProgramAndFile(fileName)
node := astnav.GetTouchingPropertyName(file, position)
if node.Kind == ast.KindSourceFile {
return nil
}
checker := program.GetTypeChecker()
calledDeclaration := tryGetSignatureDeclaration(checker, node)
if calledDeclaration != nil {
name := ast.GetNameOfDeclaration(calledDeclaration)
if name != nil {
return createLocationsFromDeclarations([]*ast.Node{name})
}
}
if symbol := checker.GetSymbolAtLocation(node); symbol != nil {
if symbol.Flags&ast.SymbolFlagsAlias != 0 {
if resolved, ok := checker.ResolveAlias(symbol); ok {
symbol = resolved
}
}
return createLocationsFromDeclarations(symbol.Declarations)
}
return nil
}
func createLocationsFromDeclarations(declarations []*ast.Node) []Location {
locations := make([]Location, 0, len(declarations))
for _, decl := range declarations {
file := ast.GetSourceFileOfNode(decl)
loc := decl.Loc
pos := scanner.GetTokenPosOfNode(decl, file, false /*includeJSDoc*/)
locations = append(locations, Location{
FileName: file.FileName(),
Range: core.NewTextRange(pos, loc.End()),
})
}
return locations
}
/** Returns a CallLikeExpression where `node` is the target being invoked. */
func getAncestorCallLikeExpression(node *ast.Node) *ast.Node {
target := ast.FindAncestor(node, func(n *ast.Node) bool {
return !ast.IsRightSideOfPropertyAccess(n)
})
callLike := target.Parent
if callLike != nil && checker.IsCallLikeExpression(callLike) && checker.GetInvokedExpression(callLike) == target {
return callLike
}
return nil
}
func tryGetSignatureDeclaration(typeChecker *checker.Checker, node *ast.Node) *ast.Node {
var signature *checker.Signature
callLike := getAncestorCallLikeExpression(node)
if callLike != nil {
signature = typeChecker.GetResolvedSignature(callLike, nil, checker.CheckModeNormal)
}
// Don't go to a function type, go to the value having that type.
var declaration *ast.Node
if signature != nil && checker.GetDeclaration(signature) != nil {
declaration = checker.GetDeclaration(signature)
if ast.IsFunctionLike(declaration) && !ast.IsFunctionTypeNode(declaration) {
return declaration
}
}
return nil
}