Skip to content

Commit 546b258

Browse files
Merge pull request #23 from grafana/julienduchesne/fix-self-scope
Fix `self` scope
2 parents bff4aba + 89da67e commit 546b258

File tree

5 files changed

+73
-1
lines changed

5 files changed

+73
-1
lines changed

pkg/position/range.go

+18
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,21 @@ func InRange(point ast.Location, theRange ast.LocationRange) bool {
4848

4949
return true
5050
}
51+
52+
// RangeGreaterOrEqual returns true if the first range is greater than the second.
53+
func RangeGreaterOrEqual(a ast.LocationRange, b ast.LocationRange) bool {
54+
if a.Begin.Line > b.Begin.Line {
55+
return false
56+
}
57+
if a.End.Line < b.End.Line {
58+
return false
59+
}
60+
if a.Begin.Line == b.Begin.Line && a.Begin.Column > b.Begin.Column {
61+
return false
62+
}
63+
if a.End.Line == b.End.Line && a.End.Column < b.End.Column {
64+
return false
65+
}
66+
67+
return true
68+
}

pkg/processing/find_field.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func FindRangesFromIndexList(stack *nodestack.NodeStack, indexList []string, vm
5151
tmpStack := nodestack.NewNodeStack(stack.From)
5252
tmpStack.Stack = make([]ast.Node, len(stack.Stack))
5353
copy(tmpStack.Stack, stack.Stack)
54-
foundDesugaredObjects = findTopLevelObjects(tmpStack, vm)
54+
foundDesugaredObjects = filterSelfScope(findTopLevelObjects(tmpStack, vm))
5555
} else if start == "std" {
5656
return nil, fmt.Errorf("cannot get definition of std lib")
5757
} else if strings.Contains(start, ".") {

pkg/processing/object.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package processing
2+
3+
import (
4+
"github.com/google/go-jsonnet/ast"
5+
"github.com/grafana/jsonnet-language-server/pkg/position"
6+
)
7+
8+
// filterSelfScope takes in an array of objects (blocks delimited by curly braces) and
9+
// returns a new array of objects, where only objects in scope of the first one are kept
10+
// This is done by comparing the location ranges. If the range of the first object is
11+
// contained within the range of another object, the latter object is removed because
12+
// it is a parent of the first object.
13+
func filterSelfScope(objs []*ast.DesugaredObject) (result []*ast.DesugaredObject) {
14+
if len(objs) == 0 {
15+
return objs
16+
}
17+
18+
// Copy the array so we don't modify the original
19+
result = objs[:]
20+
21+
topLevel := result[0]
22+
i := 1
23+
for i < len(result) {
24+
obj := result[i]
25+
// If the current object is contained within the top level object, remove it
26+
if position.RangeGreaterOrEqual(obj.LocRange, topLevel.LocRange) {
27+
result = append(result[:i], result[i+1:]...)
28+
continue
29+
}
30+
i++
31+
}
32+
return
33+
}

pkg/server/definition_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,21 @@ func TestDefinitionFail(t *testing.T) {
466466
},
467467
expected: fmt.Errorf("could not find a lhs object"),
468468
},
469+
{
470+
name: "goto self fails when out of scope",
471+
params: protocol.DefinitionParams{
472+
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
473+
TextDocument: protocol.TextDocumentIdentifier{
474+
URI: "testdata/goto-self-out-of-scope.jsonnet",
475+
},
476+
Position: protocol.Position{
477+
Line: 3,
478+
Character: 18,
479+
},
480+
},
481+
},
482+
expected: fmt.Errorf("field test was not found in ast.DesugaredObject"),
483+
},
469484
}
470485
for _, tc := range testCases {
471486
t.Run(tc.name, func(t *testing.T) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
test: 'test',
3+
sub: {
4+
test2: self.test,
5+
},
6+
}

0 commit comments

Comments
 (0)