Skip to content

Commit a23b945

Browse files
Fix world's slowest stack overflow (#123)
* Fix world's slowest stack overflow When dealing with CRDsonnet libraries in our (Grafana Labs) repositories, the language server would lock up: - I thought it had something to do with CRDsonnet but I was wrong. - This happened because it was trying to find a field in the wrong nodestack repeatedly (see image) - This PR fixes the issue. - Obviously, the language server can't find fields that come from processing jsonschema, but at least it doesn't take up 4 full CPUs (it reached a full 1% CPU usage while testing :) ) * Remove unneeded boolean All tests are still passing. `$` can be resolved across multiple files, so I guess the language server is just better now and doesn't need that safety If this causes a bug, we should add a new test
1 parent 9708978 commit a23b945

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

pkg/ast/processing/find_field.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
1515
var foundDesugaredObjects []*ast.DesugaredObject
1616
// First element will be super, self, or var name
1717
start, indexList := indexList[0], indexList[1:]
18-
sameFileOnly := false
1918
switch {
2019
case start == "super":
2120
// Find the LHS desugared object of a binary node
@@ -36,7 +35,6 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
3635
case start == "std":
3736
return nil, fmt.Errorf("cannot get definition of std lib")
3837
case start == "$":
39-
sameFileOnly = true
4038
foundDesugaredObjects = FindTopLevelObjects(nodestack.NewNodeStack(stack.From), vm)
4139
case strings.Contains(start, "."):
4240
foundDesugaredObjects = FindTopLevelObjectsInFile(vm, start, "")
@@ -66,6 +64,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
6664
case *ast.Import:
6765
filename := bodyNode.File.Value
6866
foundDesugaredObjects = FindTopLevelObjectsInFile(vm, filename, "")
67+
6968
case *ast.Index, *ast.Apply:
7069
tempStack := nodestack.NewNodeStack(bodyNode)
7170
indexList = append(tempStack.BuildIndexList(), indexList...)
@@ -80,10 +79,10 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
8079
}
8180
}
8281

83-
return extractObjectRangesFromDesugaredObjs(stack, vm, foundDesugaredObjects, sameFileOnly, indexList, partialMatchFields)
82+
return extractObjectRangesFromDesugaredObjs(vm, foundDesugaredObjects, indexList, partialMatchFields)
8483
}
8584

86-
func extractObjectRangesFromDesugaredObjs(stack *nodestack.NodeStack, vm *jsonnet.VM, desugaredObjs []*ast.DesugaredObject, sameFileOnly bool, indexList []string, partialMatchFields bool) ([]ObjectRange, error) {
85+
func extractObjectRangesFromDesugaredObjs(vm *jsonnet.VM, desugaredObjs []*ast.DesugaredObject, indexList []string, partialMatchFields bool) ([]ObjectRange, error) {
8786
var ranges []ObjectRange
8887
for len(indexList) > 0 {
8988
index := indexList[0]
@@ -135,10 +134,15 @@ func extractObjectRangesFromDesugaredObjs(stack *nodestack.NodeStack, vm *jsonne
135134
case *ast.DesugaredObject:
136135
desugaredObjs = append(desugaredObjs, fieldNode)
137136
case *ast.Index:
138-
additionalIndexList := append(nodestack.NewNodeStack(fieldNode).BuildIndexList(), indexList...)
139-
result, err := FindRangesFromIndexList(stack, additionalIndexList, vm, partialMatchFields)
140-
if len(result) > 0 {
141-
if !sameFileOnly || result[0].Filename == stack.From.Loc().FileName {
137+
// if we're trying to find the a definition which is an index,
138+
// we need to find it from itself, meaning that we need to create a stack
139+
// from the index's target and search from there
140+
rootNode, _, _ := vm.ImportAST("", fieldNode.LocRange.FileName)
141+
stack, _ := FindNodeByPosition(rootNode, fieldNode.Target.Loc().Begin)
142+
if stack != nil {
143+
additionalIndexList := append(nodestack.NewNodeStack(fieldNode).BuildIndexList(), indexList...)
144+
result, _ := FindRangesFromIndexList(stack, additionalIndexList, vm, partialMatchFields)
145+
if len(result) > 0 {
142146
return result, err
143147
}
144148
}

pkg/server/definition_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,22 @@ var definitionTestCases = []definitionTestCase{
910910
},
911911
}},
912912
},
913+
{
914+
name: "test fix infinite recursion",
915+
filename: "./testdata/goto-infinite-recursion-bug-1.jsonnet",
916+
position: protocol.Position{Line: 2, Character: 26},
917+
results: []definitionResult{{
918+
targetFilename: "testdata/goto-infinite-recursion-bug-3.libsonnet",
919+
targetRange: protocol.Range{
920+
Start: protocol.Position{Line: 5, Character: 10},
921+
End: protocol.Position{Line: 5, Character: 36},
922+
},
923+
targetSelectionRange: protocol.Range{
924+
Start: protocol.Position{Line: 5, Character: 10},
925+
End: protocol.Position{Line: 5, Character: 22},
926+
},
927+
}},
928+
},
913929
}
914930

915931
func TestDefinition(t *testing.T) {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
local drone = import './goto-infinite-recursion-bug-2.libsonnet';
2+
{
3+
steps: drone.step.withCommands([
4+
'blabla',
5+
]),
6+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
local drone = import './goto-infinite-recursion-bug-3.libsonnet';
2+
{
3+
pipeline:
4+
drone.pipeline.docker {
5+
new(name):
6+
super.new(name)
7+
+ super.clone.withRetries(3)
8+
+ super.clone.withDepth(10000)
9+
+ super.platform.withArch('amd64')
10+
+ super.withImagePullSecrets(['dockerconfigjson']),
11+
},
12+
13+
step:
14+
drone.pipeline.docker.step,
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
local lib =
2+
{
3+
pipeline: {
4+
docker: {
5+
step: {
6+
withCommands(commands): {},
7+
},
8+
},
9+
},
10+
};
11+
12+
13+
lib

0 commit comments

Comments
 (0)