Skip to content

Commit 77a93c3

Browse files
Return multiple definitions: Simple cases (#29)
* Handle multiple definitions of a first level field * Handle nested cases * Add all tests * PR comments
1 parent 1233a00 commit 77a93c3

File tree

3 files changed

+151
-30
lines changed

3 files changed

+151
-30
lines changed

pkg/processing/find_field.go

+42-30
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ func fieldToRange(field *ast.DesugaredObjectField) objectRange {
3535
}
3636

3737
func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm *jsonnet.VM) ([]objectRange, error) {
38-
var foundField *ast.DesugaredObjectField
3938
var foundDesugaredObjects []*ast.DesugaredObject
4039
// First element will be super, self, or var name
4140
start, indexList := indexList[0], indexList[1:]
@@ -99,54 +98,67 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
9998
return nil, fmt.Errorf("unexpected node type when finding bind for '%s'", start)
10099
}
101100
}
101+
var ranges []objectRange
102102
for len(indexList) > 0 {
103103
index := indexList[0]
104104
indexList = indexList[1:]
105-
foundField = findObjectFieldInObjects(foundDesugaredObjects, index)
105+
foundFields := findObjectFieldsInObjects(foundDesugaredObjects, index)
106106
foundDesugaredObjects = foundDesugaredObjects[:0]
107-
if foundField == nil {
107+
if len(foundFields) == 0 {
108108
return nil, fmt.Errorf("field %s was not found in ast.DesugaredObject", index)
109109
}
110110
if len(indexList) == 0 {
111-
return []objectRange{fieldToRange(foundField)}, nil
112-
}
113-
switch fieldNode := foundField.Body.(type) {
114-
case *ast.Var:
115-
bind := FindBindByIdViaStack(stack, fieldNode.Id)
116-
if bind == nil {
117-
return nil, fmt.Errorf("could not find bind for %s", fieldNode.Id)
111+
for _, found := range foundFields {
112+
ranges = append(ranges, fieldToRange(found))
113+
114+
// If the field is not PlusSuper (field+: value), we stop there. Other previous values are not relevant
115+
if !found.PlusSuper {
116+
break
117+
}
118118
}
119-
foundDesugaredObjects = append(foundDesugaredObjects, bind.Body.(*ast.DesugaredObject))
120-
case *ast.DesugaredObject:
121-
stack = stack.Push(fieldNode)
122-
foundDesugaredObjects = append(foundDesugaredObjects, findDesugaredObjectFromStack(stack))
123-
case *ast.Index:
124-
tempStack := nodestack.NewNodeStack(fieldNode)
125-
additionalIndexList := tempStack.BuildIndexList()
126-
additionalIndexList = append(additionalIndexList, indexList...)
127-
result, err := FindRangesFromIndexList(stack, additionalIndexList, vm)
128-
if sameFileOnly && len(result) > 0 && result[0].Filename != stack.From.Loc().FileName {
129-
continue
119+
return ranges, nil
120+
}
121+
122+
for _, foundField := range foundFields {
123+
switch fieldNode := foundField.Body.(type) {
124+
case *ast.Var:
125+
bind := FindBindByIdViaStack(stack, fieldNode.Id)
126+
if bind == nil {
127+
return nil, fmt.Errorf("could not find bind for %s", fieldNode.Id)
128+
}
129+
foundDesugaredObjects = append(foundDesugaredObjects, bind.Body.(*ast.DesugaredObject))
130+
case *ast.DesugaredObject:
131+
stack = stack.Push(fieldNode)
132+
foundDesugaredObjects = append(foundDesugaredObjects, findDesugaredObjectFromStack(stack))
133+
case *ast.Index:
134+
tempStack := nodestack.NewNodeStack(fieldNode)
135+
additionalIndexList := tempStack.BuildIndexList()
136+
additionalIndexList = append(additionalIndexList, indexList...)
137+
result, err := FindRangesFromIndexList(stack, additionalIndexList, vm)
138+
if sameFileOnly && len(result) > 0 && result[0].Filename != stack.From.Loc().FileName {
139+
continue
140+
}
141+
return result, err
142+
case *ast.Import:
143+
filename := fieldNode.File.Value
144+
rootNode, _, _ := vm.ImportAST(string(fieldNode.Loc().File.DiagnosticFileName), filename)
145+
foundDesugaredObjects = findTopLevelObjects(nodestack.NewNodeStack(rootNode), vm)
130146
}
131-
return result, err
132-
case *ast.Import:
133-
filename := fieldNode.File.Value
134-
rootNode, _, _ := vm.ImportAST(string(fieldNode.Loc().File.DiagnosticFileName), filename)
135-
foundDesugaredObjects = findTopLevelObjects(nodestack.NewNodeStack(rootNode), vm)
136147
}
137148
}
138149

139-
return []objectRange{fieldToRange(foundField)}, nil
150+
return ranges, nil
140151
}
141152

142-
func findObjectFieldInObjects(objectNodes []*ast.DesugaredObject, index string) *ast.DesugaredObjectField {
153+
func findObjectFieldsInObjects(objectNodes []*ast.DesugaredObject, index string) []*ast.DesugaredObjectField {
154+
var matchingFields []*ast.DesugaredObjectField
143155
for _, object := range objectNodes {
144156
field := findObjectFieldInObject(object, index)
145157
if field != nil {
146-
return field
158+
matchingFields = append(matchingFields, field)
147159
}
148160
}
149-
return nil
161+
return matchingFields
150162
}
151163

152164
func findObjectFieldInObject(objectNode *ast.DesugaredObject, index string) *ast.DesugaredObjectField {

pkg/server/definition_test.go

+104
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,110 @@ func TestDefinition(t *testing.T) {
461461
},
462462
}},
463463
},
464+
{
465+
name: "goto with overrides: map (multiple definitions)",
466+
filename: "testdata/goto-overrides.jsonnet",
467+
position: protocol.Position{Line: 32, Character: 22},
468+
results: []definitionResult{
469+
{
470+
targetRange: protocol.Range{
471+
Start: protocol.Position{Line: 23, Character: 2},
472+
End: protocol.Position{Line: 29, Character: 3},
473+
},
474+
targetSelectionRange: protocol.Range{
475+
Start: protocol.Position{Line: 23, Character: 2},
476+
End: protocol.Position{Line: 23, Character: 3},
477+
},
478+
},
479+
{
480+
targetRange: protocol.Range{
481+
Start: protocol.Position{Line: 14, Character: 2},
482+
End: protocol.Position{Line: 19, Character: 3},
483+
},
484+
targetSelectionRange: protocol.Range{
485+
Start: protocol.Position{Line: 14, Character: 2},
486+
End: protocol.Position{Line: 14, Character: 3},
487+
},
488+
},
489+
{
490+
targetRange: protocol.Range{
491+
Start: protocol.Position{Line: 2, Character: 2},
492+
End: protocol.Position{Line: 10, Character: 3},
493+
},
494+
targetSelectionRange: protocol.Range{
495+
Start: protocol.Position{Line: 2, Character: 2},
496+
End: protocol.Position{Line: 2, Character: 3},
497+
},
498+
},
499+
},
500+
},
501+
{
502+
name: "goto with overrides: nested map (multiple definitions)",
503+
filename: "testdata/goto-overrides.jsonnet",
504+
position: protocol.Position{Line: 33, Character: 34},
505+
results: []definitionResult{
506+
{
507+
targetRange: protocol.Range{
508+
Start: protocol.Position{Line: 25, Character: 4},
509+
End: protocol.Position{Line: 27, Character: 5},
510+
},
511+
targetSelectionRange: protocol.Range{
512+
Start: protocol.Position{Line: 25, Character: 4},
513+
End: protocol.Position{Line: 25, Character: 11},
514+
},
515+
},
516+
{
517+
targetRange: protocol.Range{
518+
Start: protocol.Position{Line: 16, Character: 4},
519+
End: protocol.Position{Line: 18, Character: 5},
520+
},
521+
targetSelectionRange: protocol.Range{
522+
Start: protocol.Position{Line: 16, Character: 4},
523+
End: protocol.Position{Line: 16, Character: 11},
524+
},
525+
},
526+
{
527+
targetRange: protocol.Range{
528+
Start: protocol.Position{Line: 4, Character: 4},
529+
End: protocol.Position{Line: 6, Character: 5},
530+
},
531+
targetSelectionRange: protocol.Range{
532+
Start: protocol.Position{Line: 4, Character: 4},
533+
End: protocol.Position{Line: 4, Character: 11},
534+
},
535+
},
536+
},
537+
},
538+
{
539+
name: "goto with overrides: string carried from super",
540+
filename: "testdata/goto-overrides.jsonnet",
541+
position: protocol.Position{Line: 35, Character: 27},
542+
results: []definitionResult{{
543+
targetRange: protocol.Range{
544+
Start: protocol.Position{Line: 3, Character: 4},
545+
End: protocol.Position{Line: 3, Character: 18},
546+
},
547+
targetSelectionRange: protocol.Range{
548+
Start: protocol.Position{Line: 3, Character: 4},
549+
End: protocol.Position{Line: 3, Character: 9},
550+
},
551+
}},
552+
},
553+
{
554+
name: "goto with overrides: nested string carried from super",
555+
filename: "testdata/goto-overrides.jsonnet",
556+
position: protocol.Position{Line: 36, Character: 44},
557+
results: []definitionResult{{
558+
targetRange: protocol.Range{
559+
Start: protocol.Position{Line: 17, Character: 6},
560+
End: protocol.Position{Line: 17, Character: 22},
561+
},
562+
targetSelectionRange: protocol.Range{
563+
Start: protocol.Position{Line: 17, Character: 6},
564+
End: protocol.Position{Line: 17, Character: 12},
565+
},
566+
}},
567+
},
464568
}
465569
for _, tc := range testCases {
466570
t.Run(tc.name, func(t *testing.T) {

pkg/server/utils_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@ import (
1111
"github.com/grafana/jsonnet-language-server/pkg/utils"
1212
"github.com/jdbaldry/go-language-server-protocol/jsonrpc2"
1313
"github.com/jdbaldry/go-language-server-protocol/lsp/protocol"
14+
"github.com/sirupsen/logrus"
1415
"github.com/stretchr/testify/require"
1516
)
1617

18+
func init() {
19+
logrus.SetLevel(logrus.WarnLevel)
20+
}
21+
1722
func absUri(t *testing.T, path string) protocol.DocumentURI {
1823
t.Helper()
1924

0 commit comments

Comments
 (0)