-
Notifications
You must be signed in to change notification settings - Fork 0
/
symbol_tree.go
114 lines (93 loc) · 2.47 KB
/
symbol_tree.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package errgoengine
type SymbolTree struct {
Parent *SymbolTree
StartPos Position
EndPos Position
Symbols map[string]Symbol
Scopes []*SymbolTree
}
func (tree *SymbolTree) CreateChildFromNode(n SyntaxNode) *SymbolTree {
nearest := tree.GetNearestScopedTree(n.StartPosition().Index)
if nearest.StartPos.Eq(n.StartPosition()) && nearest.EndPos.Eq(n.EndPosition()) {
return nearest
}
return &SymbolTree{
Parent: tree,
StartPos: n.StartPosition(),
EndPos: n.EndPosition(),
Symbols: map[string]Symbol{},
}
}
func (tree *SymbolTree) FindSymbolsByClause(findFn func(sym Symbol) bool) []Symbol {
symbols := []Symbol{}
for _, sym := range tree.Symbols {
if findFn(sym) {
symbols = append(symbols, sym)
}
}
if tree.Parent != nil {
symbols = append(symbols, tree.Parent.FindSymbolsByClause(findFn)...)
}
return symbols
}
func (tree *SymbolTree) Find(name string) Symbol {
for _, sym := range tree.Symbols {
if sym.Name() == name {
return sym
}
}
if tree.Parent != nil {
return tree.Parent.Find(name)
}
return nil
}
func (tree *SymbolTree) GetNearestScopedTree(index int) *SymbolTree {
if tree.Scopes != nil {
for _, scopedTree := range tree.Scopes {
if scopedTree == tree || scopedTree == nil {
continue
}
if index >= scopedTree.StartPos.Index && index <= scopedTree.EndPos.Index {
return scopedTree.GetNearestScopedTree(index)
}
}
}
return tree
}
func (tree *SymbolTree) GetSymbolByNode(node SyntaxNode) Symbol {
// Get nearest tree
nearestTree := tree.GetNearestScopedTree(node.StartPosition().Index)
return nearestTree.Find(node.Text())
}
func (tree *SymbolTree) Add(sym Symbol) {
if tree.Symbols == nil {
tree.Symbols = make(map[string]Symbol)
}
tree.Symbols[sym.Name()] = sym
loc := sym.Location()
if loc.StartPos.Index < tree.StartPos.Index {
tree.StartPos = loc.StartPos
}
if loc.EndPos.Index > tree.EndPos.Index {
tree.EndPos = loc.EndPos
}
if cSym := CastChildrenSymbol(sym); cSym != nil && cSym.Children() != tree {
if tree.Scopes == nil {
tree.Scopes = []*SymbolTree{}
}
// check if already exists
for _, scopedTree := range tree.Scopes {
if scopedTree == cSym.Children() {
return
}
}
tree.Scopes = append(tree.Scopes, cSym.Children())
cSym.Children().Parent = tree
if cSym.Children().StartPos.Index < tree.StartPos.Index {
tree.StartPos = cSym.Children().StartPos
}
if cSym.Children().EndPos.Index > tree.EndPos.Index {
tree.EndPos = cSym.Children().EndPos
}
}
}