this repo has no description
0
fork

Configure Feed

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

cue/errors: avoid duplicate path in error list formatting

When list.Msg returned p[0] as a format argument for multi-error lists,
the error's path would appear twice: once from list.Path
(which delegates to p[0].Path) and again when the error was
formatted as a %s argument via errorFormatter.String(),
added in https://cuelang.org/cl/1222367 to enable cycle detection.

Fix this by wrapping p[0] in a pathlessError type that overrides Path
to return nil, suppressing the duplicate path prefix while
preserving the full error chain via Unwrap.

Fixes #4171

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: I97366fd64d2bb2695b39135d89e10b48e2656a6a
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1231147
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Matthew Sackman <matthew@cue.works>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+16 -5
+12 -1
cue/errors/errors.go
··· 440 440 return fmt.Sprintf(format, args...) 441 441 } 442 442 443 + // pathlessError wraps an Error to suppress its path, for use as a 444 + // format argument when the path is already provided by the caller. 445 + type pathlessError struct{ cueError } 446 + type cueError = Error // alias to avoid field name conflicting with Error() method 447 + 448 + func (e pathlessError) Path() []string { return nil } 449 + func (e pathlessError) Unwrap() error { return Unwrap(e.cueError) } 450 + 443 451 // Msg reports the unformatted error message for the first error, if any. 444 452 func (p list) Msg() (format string, args []interface{}) { 445 453 switch len(p) { ··· 448 456 case 1: 449 457 return p[0].Msg() 450 458 } 451 - return "%s (and %d more errors)", []interface{}{p[0], len(p) - 1} 459 + // Wrap p[0] to suppress its path. The list's own Path() already 460 + // returns p[0].Path(), so including the path in the format arg 461 + // would cause it to appear twice in the output. 462 + return "%s (and %d more errors)", []interface{}{pathlessError{p[0]}, len(p) - 1} 452 463 } 453 464 454 465 // Position reports the primary position for the first error, if any.
+2 -2
cue/testdata/cycle/issue4228.txtar
··· 181 181 ./in.cue:40:8 182 182 ./in.cue:47:22 183 183 ./in.cue:65:13 184 - argocd.app.apps: <- invalid {namespace:string,revisionHistoryLimit:*3 | int,k8s:_|_(argocd.app.apps.k8s.apiVersion: argocd.app.apps.k8s.apiVersion: field not allowed (and 2 more errors)),name:string}: 184 + argocd.app.apps: <- invalid {namespace:string,revisionHistoryLimit:*3 | int,k8s:_|_(argocd.app.apps.k8s.apiVersion: field not allowed (and 2 more errors)),name:string}: 185 185 ./in.cue:16:8 186 186 ./in.cue:15:38 187 187 ./in.cue:40:8 ··· 310 310 // argocd.app.apps.k8s.metadata: field not allowed: 311 311 // ./in.cue:5:7 312 312 // ./in.cue:11:7 313 - // argocd.app.apps: <- invalid {namespace:string,revisionHistoryLimit:*3 | int,k8s:_|_(argocd.app.apps.k8s.apiVersion: argocd.app.apps.k8s.apiVersion: field not allowed (and 2 more errors)),name:string}: 313 + // argocd.app.apps: <- invalid {namespace:string,revisionHistoryLimit:*3 | int,k8s:_|_(argocd.app.apps.k8s.apiVersion: field not allowed (and 2 more errors)),name:string}: 314 314 // ./in.cue:16:8 315 315 // ./in.cue:15:38 316 316 // ./in.cue:40:8
+2 -2
pkg/list/testdata/issue4171.txtar
··· 9 9 X: ["A", "B", "C"] 10 10 -- out/list-v3 -- 11 11 Errors: 12 - X: invalid value ["A","B","C"] (does not satisfy list.IsSorted({T:number | string,x:number | string,y:number | string,less:_|_(Descending.less: Descending.less: unresolved disjunction number | string (type (string|number)) (and 1 more errors))})): 12 + X: invalid value ["A","B","C"] (does not satisfy list.IsSorted({T:number | string,x:number | string,y:number | string,less:_|_(Descending.less: unresolved disjunction number | string (type (string|number)) (and 1 more errors))})): 13 13 ./in.cue:3:4 14 14 ./in.cue:4:4 15 15 16 16 Result: 17 - X: _|_ // X: invalid value ["A","B","C"] (does not satisfy list.IsSorted({T:number | string,x:number | string,y:number | string,less:_|_(Descending.less: Descending.less: unresolved disjunction number | string (type (string|number)) (and 1 more errors))})) 17 + X: _|_ // X: invalid value ["A","B","C"] (does not satisfy list.IsSorted({T:number | string,x:number | string,y:number | string,less:_|_(Descending.less: unresolved disjunction number | string (type (string|number)) (and 1 more errors))}))