Skip to content

Commit 9dc3496

Browse files
Refactoring + Speed improvements (#36)
* Refactoring + Speed improvements Removed unnecessary return values in node stack Added an import cache bringing massive perfomance improvements * Fix imports * Rename some vars
1 parent 6698fa1 commit 9dc3496

File tree

10 files changed

+149
-127
lines changed

10 files changed

+149
-127
lines changed

pkg/nodestack/nodestack.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,18 @@ func (s *NodeStack) Clone() *NodeStack {
2525
}
2626
}
2727

28-
func (s *NodeStack) Push(n ast.Node) *NodeStack {
28+
func (s *NodeStack) Push(n ast.Node) {
2929
s.Stack = append(s.Stack, n)
30-
return s
3130
}
3231

33-
func (s *NodeStack) Pop() (*NodeStack, ast.Node) {
32+
func (s *NodeStack) Pop() ast.Node {
3433
l := len(s.Stack)
3534
if l == 0 {
36-
return s, nil
35+
return nil
3736
}
3837
n := s.Stack[l-1]
3938
s.Stack = s.Stack[:l-1]
40-
return s, n
39+
return n
4140
}
4241

4342
func (s *NodeStack) Peek() ast.Node {
@@ -54,14 +53,14 @@ func (s *NodeStack) IsEmpty() bool {
5453
func (s *NodeStack) BuildIndexList() []string {
5554
var indexList []string
5655
for !s.IsEmpty() {
57-
_, curr := s.Pop()
56+
curr := s.Pop()
5857
switch curr := curr.(type) {
5958
case *ast.SuperIndex:
60-
s = s.Push(curr.Index)
59+
s.Push(curr.Index)
6160
indexList = append(indexList, "super")
6261
case *ast.Index:
63-
s = s.Push(curr.Index)
64-
s = s.Push(curr.Target)
62+
s.Push(curr.Index)
63+
s.Push(curr.Target)
6564
case *ast.LiteralString:
6665
indexList = append(indexList, curr.Value)
6766
case *ast.Self:

pkg/processing/find_bind.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ import (
66
)
77

88
func FindBindByIdViaStack(stack *nodestack.NodeStack, id ast.Identifier) *ast.LocalBind {
9-
stack = stack.Clone()
10-
for !stack.IsEmpty() {
11-
_, curr := stack.Pop()
12-
switch curr := curr.(type) {
9+
for _, node := range stack.Stack {
10+
switch curr := node.(type) {
1311
case *ast.Local:
1412
for _, bind := range curr.Binds {
1513
if bind.Variable == id {
@@ -23,7 +21,6 @@ func FindBindByIdViaStack(stack *nodestack.NodeStack, id ast.Identifier) *ast.Lo
2321
}
2422
}
2523
}
26-
2724
}
2825
return nil
2926
}

pkg/processing/find_field.go

Lines changed: 44 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
5959
} else if start == "std" {
6060
return nil, fmt.Errorf("cannot get definition of std lib")
6161
} else if strings.Contains(start, ".") {
62-
rootNode, _, _ := vm.ImportAST("", start)
63-
foundDesugaredObjects = findTopLevelObjects(nodestack.NewNodeStack(rootNode), vm)
62+
foundDesugaredObjects = findTopLevelObjectsInFile(vm, start, "")
6463
} else if start == "$" {
6564
sameFileOnly = true
6665
foundDesugaredObjects = findTopLevelObjects(nodestack.NewNodeStack(stack.From), vm)
@@ -88,8 +87,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
8887
foundDesugaredObjects = findTopLevelObjects(tmpStack, vm)
8988
case *ast.Import:
9089
filename := bodyNode.File.Value
91-
rootNode, _, _ := vm.ImportAST("", filename)
92-
foundDesugaredObjects = findTopLevelObjects(nodestack.NewNodeStack(rootNode), vm)
90+
foundDesugaredObjects = findTopLevelObjectsInFile(vm, filename, "")
9391
case *ast.Index:
9492
tempStack := nodestack.NewNodeStack(bodyNode)
9593
indexList = append(tempStack.BuildIndexList(), indexList...)
@@ -103,7 +101,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
103101
index := indexList[0]
104102
indexList = indexList[1:]
105103
foundFields := findObjectFieldsInObjects(foundDesugaredObjects, index)
106-
foundDesugaredObjects = foundDesugaredObjects[:0]
104+
foundDesugaredObjects = nil
107105
if len(foundFields) == 0 {
108106
return nil, fmt.Errorf("field %s was not found in ast.DesugaredObject", index)
109107
}
@@ -119,31 +117,9 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
119117
return ranges, nil
120118
}
121119

122-
// Unpack:
123-
// - Binary nodes. A field could be either in the left or right side of the binary
124-
// - Self nodes. We want the object self refers to, not the self node itself
125-
var fieldNodes []ast.Node
126-
for _, foundField := range foundFields {
127-
switch fieldNode := foundField.Body.(type) {
128-
case *ast.Self:
129-
filename := fieldNode.LocRange.FileName
130-
rootNode, _, _ := vm.ImportAST("", filename)
131-
tmpStack, err := FindNodeByPosition(rootNode, fieldNode.LocRange.Begin)
132-
if err != nil {
133-
return nil, err
134-
}
135-
for !tmpStack.IsEmpty() {
136-
_, node := tmpStack.Pop()
137-
if _, ok := node.(*ast.DesugaredObject); ok {
138-
fieldNodes = append(fieldNodes, node)
139-
}
140-
}
141-
case *ast.Binary:
142-
fieldNodes = append(fieldNodes, fieldNode.Right)
143-
fieldNodes = append(fieldNodes, fieldNode.Left)
144-
default:
145-
fieldNodes = append(fieldNodes, fieldNode)
146-
}
120+
fieldNodes, err := unpackFieldNodes(vm, foundFields)
121+
if err != nil {
122+
return nil, err
147123
}
148124

149125
for _, fieldNode := range fieldNodes {
@@ -155,7 +131,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
155131
}
156132
foundDesugaredObjects = append(foundDesugaredObjects, varReference.(*ast.DesugaredObject))
157133
case *ast.DesugaredObject:
158-
stack = stack.Push(fieldNode)
134+
stack.Push(fieldNode)
159135
foundDesugaredObjects = append(foundDesugaredObjects, findDesugaredObjectFromStack(stack))
160136
case *ast.Index:
161137
tempStack := nodestack.NewNodeStack(fieldNode)
@@ -168,15 +144,46 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
168144
return result, err
169145
case *ast.Import:
170146
filename := fieldNode.File.Value
171-
rootNode, _, _ := vm.ImportAST(string(fieldNode.Loc().File.DiagnosticFileName), filename)
172-
foundDesugaredObjects = append(foundDesugaredObjects, findTopLevelObjects(nodestack.NewNodeStack(rootNode), vm)...)
147+
newObjs := findTopLevelObjectsInFile(vm, filename, string(fieldNode.Loc().File.DiagnosticFileName))
148+
foundDesugaredObjects = append(foundDesugaredObjects, newObjs...)
173149
}
174150
}
175151
}
176152

177153
return ranges, nil
178154
}
179155

156+
// unpackFieldNodes extracts nodes from fields
157+
// - Binary nodes. A field could be either in the left or right side of the binary
158+
// - Self nodes. We want the object self refers to, not the self node itself
159+
func unpackFieldNodes(vm *jsonnet.VM, fields []*ast.DesugaredObjectField) ([]ast.Node, error) {
160+
var fieldNodes []ast.Node
161+
for _, foundField := range fields {
162+
switch fieldNode := foundField.Body.(type) {
163+
case *ast.Self:
164+
filename := fieldNode.LocRange.FileName
165+
rootNode, _, _ := vm.ImportAST("", filename)
166+
tmpStack, err := FindNodeByPosition(rootNode, fieldNode.LocRange.Begin)
167+
if err != nil {
168+
return nil, err
169+
}
170+
for !tmpStack.IsEmpty() {
171+
node := tmpStack.Pop()
172+
if _, ok := node.(*ast.DesugaredObject); ok {
173+
fieldNodes = append(fieldNodes, node)
174+
}
175+
}
176+
case *ast.Binary:
177+
fieldNodes = append(fieldNodes, fieldNode.Right)
178+
fieldNodes = append(fieldNodes, fieldNode.Left)
179+
default:
180+
fieldNodes = append(fieldNodes, fieldNode)
181+
}
182+
}
183+
184+
return fieldNodes, nil
185+
}
186+
180187
func findObjectFieldsInObjects(objectNodes []*ast.DesugaredObject, index string) []*ast.DesugaredObjectField {
181188
var matchingFields []*ast.DesugaredObjectField
182189
for _, object := range objectNodes {
@@ -207,7 +214,7 @@ func findObjectFieldInObject(objectNode *ast.DesugaredObject, index string) *ast
207214

208215
func findDesugaredObjectFromStack(stack *nodestack.NodeStack) *ast.DesugaredObject {
209216
for !stack.IsEmpty() {
210-
_, curr := stack.Pop()
217+
curr := stack.Pop()
211218
switch curr := curr.(type) {
212219
case *ast.DesugaredObject:
213220
return curr
@@ -216,47 +223,6 @@ func findDesugaredObjectFromStack(stack *nodestack.NodeStack) *ast.DesugaredObje
216223
return nil
217224
}
218225

219-
// Find all ast.DesugaredObject's from NodeStack
220-
func findTopLevelObjects(stack *nodestack.NodeStack, vm *jsonnet.VM) []*ast.DesugaredObject {
221-
var objects []*ast.DesugaredObject
222-
for !stack.IsEmpty() {
223-
_, curr := stack.Pop()
224-
switch curr := curr.(type) {
225-
case *ast.DesugaredObject:
226-
objects = append(objects, curr)
227-
case *ast.Binary:
228-
stack = stack.Push(curr.Left)
229-
stack = stack.Push(curr.Right)
230-
case *ast.Local:
231-
stack = stack.Push(curr.Body)
232-
case *ast.Import:
233-
filename := curr.File.Value
234-
rootNode, _, _ := vm.ImportAST(string(curr.Loc().File.DiagnosticFileName), filename)
235-
stack = stack.Push(rootNode)
236-
case *ast.Index:
237-
container := stack.Peek()
238-
if containerObj, containerIsObj := container.(*ast.DesugaredObject); containerIsObj {
239-
indexValue, indexIsString := curr.Index.(*ast.LiteralString)
240-
if !indexIsString {
241-
continue
242-
}
243-
obj := findObjectFieldInObject(containerObj, indexValue.Value)
244-
if obj != nil {
245-
stack.Push(obj.Body)
246-
}
247-
}
248-
case *ast.Var:
249-
varReference, err := findVarReference(curr, vm)
250-
if err != nil {
251-
log.WithError(err).Errorf("Error finding var reference, ignoring this node")
252-
continue
253-
}
254-
stack.Push(varReference)
255-
}
256-
}
257-
return objects
258-
}
259-
260226
// findVarReference finds the object that the variable is referencing
261227
// To do so, we get the stack where the var is used and search that stack for the var's definition
262228
func findVarReference(varNode *ast.Var, vm *jsonnet.VM) (ast.Node, error) {
@@ -274,7 +240,7 @@ func findVarReference(varNode *ast.Var, vm *jsonnet.VM) (ast.Node, error) {
274240

275241
func findLhsDesugaredObject(stack *nodestack.NodeStack) (*ast.DesugaredObject, error) {
276242
for !stack.IsEmpty() {
277-
_, curr := stack.Pop()
243+
curr := stack.Pop()
278244
switch curr := curr.(type) {
279245
case *ast.Binary:
280246
lhsNode := curr.Left
@@ -289,10 +255,10 @@ func findLhsDesugaredObject(stack *nodestack.NodeStack) (*ast.DesugaredObject, e
289255
}
290256
case *ast.Local:
291257
for _, bind := range curr.Binds {
292-
stack = stack.Push(bind.Body)
258+
stack.Push(bind.Body)
293259
}
294260
if curr.Body != nil {
295-
stack = stack.Push(curr.Body)
261+
stack.Push(curr.Body)
296262
}
297263
}
298264
}

pkg/processing/find_param.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ import (
66
)
77

88
func FindParameterByIdViaStack(stack *nodestack.NodeStack, id ast.Identifier) *ast.Parameter {
9-
stack = stack.Clone()
10-
for !stack.IsEmpty() {
11-
_, curr := stack.Pop()
12-
switch curr := curr.(type) {
13-
case *ast.Function:
14-
for _, param := range curr.Parameters {
9+
for _, node := range stack.Stack {
10+
if f, ok := node.(*ast.Function); ok {
11+
for _, param := range f.Parameters {
1512
if param.Name == id {
1613
return &param
1714
}
1815
}
1916
}
20-
2117
}
2218
return nil
2319
}

pkg/processing/find_position.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,77 +19,77 @@ func FindNodeByPosition(node ast.Node, location ast.Location) (*nodestack.NodeSt
1919
searchStack := &nodestack.NodeStack{From: stack.From}
2020
var curr ast.Node
2121
for !stack.IsEmpty() {
22-
stack, curr = stack.Pop()
22+
curr = stack.Pop()
2323
// This is needed because SuperIndex only spans "key: super" and not the ".foo" after. This only occurs
2424
// when super only has 1 additional index. "super.foo.bar" will not have this issue
2525
if curr, isType := curr.(*ast.SuperIndex); isType {
2626
curr.Loc().End.Column = curr.Loc().End.Column + len(curr.Index.(*ast.LiteralString).Value) + 1
2727
}
2828
inRange := position.InRange(location, *curr.Loc())
2929
if inRange {
30-
searchStack = searchStack.Push(curr)
30+
searchStack.Push(curr)
3131
} else if curr.Loc().End.IsSet() {
3232
continue
3333
}
3434
switch curr := curr.(type) {
3535
case *ast.Local:
3636
for _, bind := range curr.Binds {
37-
stack = stack.Push(bind.Body)
37+
stack.Push(bind.Body)
3838
}
3939
if curr.Body != nil {
40-
stack = stack.Push(curr.Body)
40+
stack.Push(curr.Body)
4141
}
4242
case *ast.DesugaredObject:
4343
for _, field := range curr.Fields {
4444
body := field.Body
4545
// Functions do not have a LocRange, so we use the one from the field's body
4646
if funcBody, isFunc := body.(*ast.Function); isFunc {
4747
funcBody.LocRange = field.LocRange
48-
stack = stack.Push(funcBody)
48+
stack.Push(funcBody)
4949
} else {
50-
stack = stack.Push(body)
50+
stack.Push(body)
5151
}
5252
}
5353
for _, local := range curr.Locals {
54-
stack = stack.Push(local.Body)
54+
stack.Push(local.Body)
5555
}
5656
case *ast.Binary:
57-
stack = stack.Push(curr.Left)
58-
stack = stack.Push(curr.Right)
57+
stack.Push(curr.Left)
58+
stack.Push(curr.Right)
5959
case *ast.Array:
6060
for _, element := range curr.Elements {
61-
stack = stack.Push(element.Expr)
61+
stack.Push(element.Expr)
6262
}
6363
case *ast.Apply:
6464
for _, posArg := range curr.Arguments.Positional {
65-
stack = stack.Push(posArg.Expr)
65+
stack.Push(posArg.Expr)
6666
}
6767
for _, namedArg := range curr.Arguments.Named {
68-
stack = stack.Push(namedArg.Arg)
68+
stack.Push(namedArg.Arg)
6969
}
70-
stack = stack.Push(curr.Target)
70+
stack.Push(curr.Target)
7171
case *ast.Conditional:
72-
stack = stack.Push(curr.Cond)
73-
stack = stack.Push(curr.BranchTrue)
74-
stack = stack.Push(curr.BranchFalse)
72+
stack.Push(curr.Cond)
73+
stack.Push(curr.BranchTrue)
74+
stack.Push(curr.BranchFalse)
7575
case *ast.Error:
76-
stack = stack.Push(curr.Expr)
76+
stack.Push(curr.Expr)
7777
case *ast.Function:
7878
for _, param := range curr.Parameters {
7979
if param.DefaultArg != nil {
80-
stack = stack.Push(param.DefaultArg)
80+
stack.Push(param.DefaultArg)
8181
}
8282
}
83-
stack = stack.Push(curr.Body)
83+
stack.Push(curr.Body)
8484
case *ast.Index:
85-
stack = stack.Push(curr.Target)
86-
stack = stack.Push(curr.Index)
85+
stack.Push(curr.Target)
86+
stack.Push(curr.Index)
8787
case *ast.InSuper:
88-
stack = stack.Push(curr.Index)
88+
stack.Push(curr.Index)
8989
case *ast.SuperIndex:
90-
stack = stack.Push(curr.Index)
90+
stack.Push(curr.Index)
9191
case *ast.Unary:
92-
stack = stack.Push(curr.Expr)
92+
stack.Push(curr.Expr)
9393
}
9494
}
9595
return searchStack.ReorderDesugaredObjects(), nil

0 commit comments

Comments
 (0)