Skip to content

Commit 49e295b

Browse files
committed
cue: try harder to find a position for Pos
Fixes #1459 Signed-off-by: Marcel van Lohuizen <mpvl@golang.org> Change-Id: I31ddee08e9db3d2c0e77a1ac91b9407994f2cd45 Signed-off-by: Marcel van Lohuizen <mpvl@golang.org> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/533468 Reviewed-by: Paul Jolly <paul@myitcv.io>
1 parent 2421553 commit 49e295b

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

cue/types.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,12 +1107,33 @@ func (v Value) Err() error {
11071107
}
11081108

11091109
// Pos returns position information.
1110+
//
1111+
// Use v.Expr to get positions for all conjuncts and disjuncts.
11101112
func (v Value) Pos() token.Pos {
1111-
if v.v == nil || v.Source() == nil {
1113+
if v.v == nil {
11121114
return token.NoPos
11131115
}
1114-
pos := v.Source().Pos()
1115-
return pos
1116+
1117+
if src := v.Source(); src != nil {
1118+
if pos := src.Pos(); pos != token.NoPos {
1119+
return pos
1120+
}
1121+
}
1122+
// Pick the most-concrete field.
1123+
var p token.Pos
1124+
for _, c := range v.v.Conjuncts {
1125+
x := c.Elem()
1126+
pp := pos(x)
1127+
if pp == token.NoPos {
1128+
continue
1129+
}
1130+
p = pp
1131+
// Prefer struct conjuncts with actual fields.
1132+
if s, ok := x.(*adt.StructLit); ok && len(s.Fields) > 0 {
1133+
break
1134+
}
1135+
}
1136+
return p
11161137
}
11171138

11181139
// TODO: IsFinal: this value can never be changed.

cue/types_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,6 +2918,51 @@ func TestReferencePath(t *testing.T) {
29182918
}
29192919
}
29202920

2921+
func TestPos(t *testing.T) {
2922+
testCases := []struct {
2923+
value string
2924+
pos string
2925+
}{{
2926+
value: `
2927+
a: string
2928+
a: "foo"`,
2929+
pos: "3:4",
2930+
}, {
2931+
value: `
2932+
a: x: string
2933+
a: x: "x"`,
2934+
pos: "2:4",
2935+
}, {
2936+
// Prefer struct conjuncts with actual fields.
2937+
value: `
2938+
a: [string]: string
2939+
a: x: "x"`,
2940+
pos: "3:4",
2941+
}, {
2942+
value: `
2943+
a: [string]: [string]: string
2944+
a: x: y: "x"`,
2945+
pos: "3:4",
2946+
}, {
2947+
value: `
2948+
a: [string]: [string]: [string]: string
2949+
a: x: y: z: "x"`,
2950+
pos: "3:4",
2951+
}}
2952+
for _, tc := range testCases {
2953+
t.Run("", func(t *testing.T) {
2954+
var c Context
2955+
c.runtime().Init()
2956+
v := c.CompileString(tc.value)
2957+
v = v.LookupPath(ParsePath("a"))
2958+
pos := v.Pos().String()
2959+
if pos != tc.pos {
2960+
t.Errorf("got %v; want %v", pos, tc.pos)
2961+
}
2962+
})
2963+
}
2964+
}
2965+
29212966
func TestPathCorrection(t *testing.T) {
29222967
testCases := []struct {
29232968
input string

0 commit comments

Comments
 (0)