From 111d05f3582c8c2a5cfbf8ce49bb5553ce7cf96a Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Tue, 11 Oct 2022 21:52:45 -0400 Subject: [PATCH] Find definitions through function applies Started in https://github.com/grafana/jsonnet-language-server/pull/63 and https://github.com/grafana/jsonnet-language-server/pull/70 I think this now covers all (or most) cases Most of this PR is just tests, since the missing code was just missing a few cases in switch cases --- pkg/ast/processing/find_field.go | 2 +- pkg/ast/processing/top_level_objects.go | 2 + pkg/nodestack/nodestack.go | 4 +- pkg/server/definition_test.go | 103 ++++++++++++++++-- .../testdata/goto-root-function-lib.libsonnet | 7 ++ .../testdata/goto-root-function.jsonnet | 13 +++ 6 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 pkg/server/testdata/goto-root-function-lib.libsonnet create mode 100644 pkg/server/testdata/goto-root-function.jsonnet diff --git a/pkg/ast/processing/find_field.go b/pkg/ast/processing/find_field.go index b32abcd..a44f0e9 100644 --- a/pkg/ast/processing/find_field.go +++ b/pkg/ast/processing/find_field.go @@ -66,7 +66,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm case *ast.Import: filename := bodyNode.File.Value foundDesugaredObjects = findTopLevelObjectsInFile(vm, filename, "") - case *ast.Index: + case *ast.Index, *ast.Apply: tempStack := nodestack.NewNodeStack(bodyNode) indexList = append(tempStack.BuildIndexList(), indexList...) return FindRangesFromIndexList(stack, indexList, vm) diff --git a/pkg/ast/processing/top_level_objects.go b/pkg/ast/processing/top_level_objects.go index 0d53869..859f3b5 100644 --- a/pkg/ast/processing/top_level_objects.go +++ b/pkg/ast/processing/top_level_objects.go @@ -55,6 +55,8 @@ func findTopLevelObjects(stack *nodestack.NodeStack, vm *jsonnet.VM) []*ast.Desu continue } stack.Push(varReference) + case *ast.Function: + stack.Push(curr.Body) } } return objects diff --git a/pkg/nodestack/nodestack.go b/pkg/nodestack/nodestack.go index f901468..d215c63 100644 --- a/pkg/nodestack/nodestack.go +++ b/pkg/nodestack/nodestack.go @@ -56,9 +56,7 @@ func (s *NodeStack) BuildIndexList() []string { curr := s.Pop() switch curr := curr.(type) { case *ast.Apply: - if target, ok := curr.Target.(*ast.Var); ok { - indexList = append(indexList, string(target.Id)) - } + s.Push(curr.Target) case *ast.SuperIndex: s.Push(curr.Index) indexList = append(indexList, "super") diff --git a/pkg/server/definition_test.go b/pkg/server/definition_test.go index 28c20fc..9883209 100644 --- a/pkg/server/definition_test.go +++ b/pkg/server/definition_test.go @@ -798,6 +798,102 @@ var definitionTestCases = []definitionTestCase{ }, }}, }, + { + name: "goto attribute of root-function library", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 5, Character: 70}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 22}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 11}, + }, + }}, + }, + { + name: "goto attribute of root-function library through local import", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 6, Character: 28}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 22}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 11}, + }, + }}, + }, + { + name: "goto attribute of root-function library through local resolved import", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 7, Character: 36}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 22}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 11}, + }, + }}, + }, + { + name: "goto nested attribute of root-function library", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 9, Character: 98}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 36}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 19}, + }, + }}, + }, + { + name: "goto nested attribute of root-function library through local import", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 10, Character: 55}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 36}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 19}, + }, + }}, + }, + { + name: "goto nested attribute of root-function library through local resolved import", + filename: "testdata/goto-root-function.jsonnet", + position: protocol.Position{Line: 11, Character: 64}, + results: []definitionResult{{ + targetFilename: "testdata/goto-root-function-lib.libsonnet", + targetRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 36}, + }, + targetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 4, Character: 4}, + End: protocol.Position{Line: 4, Character: 19}, + }, + }}, + }, } func TestDefinition(t *testing.T) { @@ -891,13 +987,6 @@ func TestDefinitionFail(t *testing.T) { position: protocol.Position{Line: 0, Character: 1}, expected: fmt.Errorf("cannot find definition"), }, - - { - name: "goto range index fails", - filename: "testdata/goto-local-function.libsonnet", - position: protocol.Position{Line: 15, Character: 57}, - expected: fmt.Errorf("unexpected node type when finding bind for 'ports': *ast.Apply"), - }, { name: "goto super fails as no LHS object exists", filename: "testdata/goto-local-function.libsonnet", diff --git a/pkg/server/testdata/goto-root-function-lib.libsonnet b/pkg/server/testdata/goto-root-function-lib.libsonnet new file mode 100644 index 0000000..41add8c --- /dev/null +++ b/pkg/server/testdata/goto-root-function-lib.libsonnet @@ -0,0 +1,7 @@ +function(attribute) { + attribute: attribute, + + nestedFunc(nestedAttribute):: { + nestedAttribute: nestedAttribute, + }, +} diff --git a/pkg/server/testdata/goto-root-function.jsonnet b/pkg/server/testdata/goto-root-function.jsonnet new file mode 100644 index 0000000..9eb4f5b --- /dev/null +++ b/pkg/server/testdata/goto-root-function.jsonnet @@ -0,0 +1,13 @@ +local lib = import 'goto-root-function-lib.libsonnet'; +local libResolved = (import 'goto-root-function-lib.libsonnet')('test'); + +{ + + fromImport: (import 'goto-root-function-lib.libsonnet')('test').attribute, + fromLib: lib('test').attribute, + fromResolvedLib: libResolved.attribute, + + nestedFromImport: (import 'goto-root-function-lib.libsonnet')('test').nestedFunc('test').nestedAttribute, + nestedFromLib: lib('test').nestedFunc('test').nestedAttribute, + nestedFromResolvedLib: libResolved.nestedFunc('test').nestedAttribute, +}