this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/adt/core: improve validation error positions

When we traverse over a shared struct, we should
remember that position.

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: Ia634978df7a96a025fec770cc45b3c77e8782c34
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1220037
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>

+90 -8
+1
cmd/cue/cmd/testdata/script/export_required.txtar
··· 29 29 ./y.cue:1:4 30 30 b.x: field is required but not present: 31 31 ./y.cue:5:2 32 + ./y.cue:8:4
+9
cue/testdata/builtins/056_issue314.txtar
··· 146 146 // [incomplete] #U.out: error in call to encoding/yaml.Marshal: incomplete value string: 147 147 // ./in.cue:26:7 148 148 // ./in.cue:25:7 149 + // ./in.cue:26:26 149 150 } 150 151 } 151 152 } ··· 162 163 } 163 164 } 164 165 #V: (#struct){ 166 + @@ -24,6 +24,7 @@ 167 + // [incomplete] #U.out: error in call to encoding/yaml.Marshal: incomplete value string: 168 + // ./in.cue:26:7 169 + // ./in.cue:25:7 170 + + // ./in.cue:26:26 171 + } 172 + } 173 + } 165 174 -- out/eval -- 166 175 (struct){ 167 176 x: (#struct){
+47
cue/testdata/fulleval/051_detectIncompleteYAML.txtar
··· 74 74 Unifications: 17 75 75 Conjuncts: 32 76 76 Disjuncts: 17 77 + -- out/evalalpha -- 78 + (struct){ 79 + #Spec: (#struct){ 80 + _vars(:foobar): (#struct){ 81 + something: (string){ string } 82 + } 83 + data: (#struct){ 84 + #foo: (#struct){ 85 + use: (string){ string } 86 + } 87 + baz: (_|_){ 88 + // [incomplete] #Spec.data.baz: non-concrete argument 0: 89 + // ./in.cue:11:11 90 + } 91 + foobar: (_|_){ 92 + // [incomplete] #Spec.data.foobar: error in call to encoding/yaml.Marshal: incomplete value string: 93 + // ./in.cue:12:11 94 + // ./in.cue:6:21 95 + // ./in.cue:9:9 96 + } 97 + } 98 + } 99 + Val: (#struct){ 100 + _vars(:foobar): (#struct){ 101 + something: (string){ "var-string" } 102 + } 103 + data: (#struct){ 104 + #foo: (#struct){ 105 + use: (string){ "var-string" } 106 + } 107 + baz: (string){ "var-string\n" } 108 + foobar: (string){ "use: var-string\n" } 109 + } 110 + } 111 + } 112 + -- diff/-out/evalalpha<==>+out/eval -- 113 + diff old new 114 + --- old 115 + +++ new 116 + @@ -15,6 +15,7 @@ 117 + // [incomplete] #Spec.data.foobar: error in call to encoding/yaml.Marshal: incomplete value string: 118 + // ./in.cue:12:11 119 + // ./in.cue:6:21 120 + + // ./in.cue:9:9 121 + } 122 + } 123 + } 77 124 -- out/eval -- 78 125 (struct){ 79 126 #Spec: (#struct){
+4 -1
internal/core/adt/errors.go
··· 228 228 } 229 229 } 230 230 231 - func NewRequiredNotPresentError(ctx *OpContext, v *Vertex) *Bottom { 231 + func NewRequiredNotPresentError(ctx *OpContext, v *Vertex, morePositions ...Node) *Bottom { 232 232 saved := ctx.PushArc(v) 233 233 err := ctx.Newf("field is required but not present") 234 + for _, p := range morePositions { 235 + err.AddPosition(p) 236 + } 234 237 v.VisitLeafConjuncts(func(c Conjunct) bool { 235 238 if f, ok := c.x.(*Field); ok && f.ArcType == ArcRequired { 236 239 err.AddPosition(c.x)
+23 -2
internal/core/adt/validate.go
··· 73 73 err *Bottom 74 74 inDefinition int 75 75 76 + sharedPositions []Node 77 + 76 78 // shared vertices should be visited at least once if referenced by 77 79 // a non-definition. 78 80 // TODO: we could also keep track of the number of references to a 79 81 // shared vertex. This would allow us to report more than a single error 80 82 // per shared vertex. 81 83 visited map[*Vertex]bool 84 + } 85 + 86 + func (v *validator) addPositions(err *ValueError) { 87 + for _, p := range v.sharedPositions { 88 + err.AddPosition(p) 89 + } 82 90 } 83 91 84 92 func (v *validator) checkConcrete() bool { ··· 104 112 105 113 y := x 106 114 115 + if x.IsShared { 116 + saved := v.sharedPositions 117 + // assume there is always a single conjunct: multiple references either 118 + // result in the same shared value, or no sharing. And there has to be 119 + // at least one to be able to share in the first place. 120 + c, n := x.SingleConjunct() 121 + if n >= 1 { 122 + v.sharedPositions = append(v.sharedPositions, c.Elem()) 123 + } 124 + defer func() { v.sharedPositions = saved }() 125 + } 107 126 // Dereference values, but only those that are not shared. This includes let 108 127 // values. This prevents us from processing structure-shared nodes more than 109 128 // once and prevents potential cycles. ··· 146 165 x = x.Default() 147 166 if !IsConcrete(x) { 148 167 x := x.Value() 168 + err := v.ctx.Newf("incomplete value %v", x) 169 + v.addPositions(err) 149 170 v.add(&Bottom{ 150 171 Code: IncompleteError, 151 - Err: v.ctx.Newf("incomplete value %v", x), 172 + Err: err, 152 173 }) 153 174 } 154 175 } ··· 156 177 for _, a := range x.Arcs { 157 178 if a.ArcType == ArcRequired && v.Final && v.inDefinition == 0 { 158 179 v.ctx.PushArcAndLabel(a) 159 - v.add(NewRequiredNotPresentError(v.ctx, a)) 180 + v.add(NewRequiredNotPresentError(v.ctx, a, v.sharedPositions...)) 160 181 v.ctx.PopArcAndLabel(a) 161 182 continue 162 183 }
+6 -5
internal/core/adt/validate_test.go
··· 300 300 #Def: a: x!: int 301 301 b: #Def 302 302 `, 303 - // TODO: \n test:3:7", only works without structure sharing. 304 303 out: `incomplete 305 304 b.a.x: field is required but not present: 306 - test:2:13`, 307 - skipNoShare: true, 305 + test:2:13 306 + test:3:7`, 308 307 }, { 309 308 // Issue #3864: issue resulting from structure sharing. 310 309 name: "attribute incomplete values in definitions to concrete path", ··· 325 324 `, 326 325 out: `incomplete 327 326 config.v.x.y: incomplete value string: 328 - test:2:11`}} 327 + test:2:11 328 + test:3:11`, 329 + skipNoShare: true, 330 + }} 329 331 330 332 cuetdtest.Run(t, testCases, func(t *cuetdtest.T, tc *testCase) { 331 333 t.Update(cuetest.UpdateGoldenFiles) 332 334 if tc.skipNoShare { 333 335 t.M.TODO_NoSharing(t) 334 336 } 335 - 336 337 r := t.M.Runtime() 337 338 ctx := eval.NewContext(r, nil) 338 339