this repo has no description
0
fork

Configure Feed

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

cue/ast/astutil: add test coverage for redeclared alias errors

TestResolve previously walked the AST and printed identifier
resolutions but discarded any errors emitted by astutil.Resolve. Add
an "errors" output section so each txtar can assert the diagnostics
produced for the files it covers, using errors.Print with the test's
Cwd so paths stay repo-relative.

Add a new redeclared.txtar that pins down the scenarios in which an
alias clashes with another alias or with a regular field of the same
name: old-style label aliases, postfix single-form, postfix dual-form
field reference (V), let clauses, and alias/field name clashes. The
suite also includes the postfix dual-form label-name capture (K) case
from the issue, which silently swallows the redeclaration today; the
file carries an inline TODO so the missing diagnostic is visible and
will surface as a golden diff once fixed.

import.txtar records the long-standing "no cue.mod/module.cue" error
that the harness previously hid, and postfix.txtar gains an
@experiment(aliasv2) attribute on each file so its experiment-gate
errors no longer leak into the new errors output.

Updates #4342.

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

+85 -1
+6
cue/ast/astutil/resolve_test.go
··· 21 21 "text/tabwriter" 22 22 23 23 "cuelang.org/go/cue/ast" 24 + "cuelang.org/go/cue/errors" 24 25 "cuelang.org/go/internal/astinternal" 25 26 "cuelang.org/go/internal/cuetxtar" 26 27 ) ··· 37 38 // Resolve is used just after parsing anyway, so lower level 38 39 // is more appropriate. 39 40 a := t.RawInstances()[0] 41 + 42 + if a.Err != nil { 43 + b := t.Writer("errors") 44 + errors.Print(b, a.Err, &errors.Config{Cwd: t.Dir, ToSlash: true}) 45 + } 40 46 41 47 for _, f := range a.Files { 42 48 if filepath.Ext(f.Filename) != ".cue" {
+3
cue/ast/astutil/testdata/resolve/import.txtar
··· 17 17 9[baz]: Scope: 0[<nil>] Node: 3["foo.com/bar:baz"] 18 18 10[p]: Scope: 0[<nil>] Node: 4["other.org/p@v1"] 19 19 11[q]: Scope: 0[<nil>] Node: 5["other.org/p@v2:q"] 20 + -- out/resolve/errors -- 21 + import failed: imports are unavailable because there is no cue.mod/module.cue file: 22 + ./in.cue:2:2
+9 -1
cue/ast/astutil/testdata/resolve/postfix.txtar
··· 1 1 -- simple.cue -- 2 + @experiment(aliasv2) 3 + 2 4 a~X: 1 3 5 b: X 4 6 c: a ··· 10 12 9[c]: Scope: 0[<nil>] Node: 0[] 11 13 10[a]: Scope: 1[*ast.File] Node: 0[1] 12 14 -- dual.cue -- 15 + @experiment(aliasv2) 16 + 13 17 a~(K, V): 1 14 18 b: K 15 19 c: V ··· 21 25 7[b]: Scope: 0[<nil>] Node: 0[] 22 26 8[K]: Scope: 2[*ast.Field] Node: 4[K] 23 27 10[c]: Scope: 0[<nil>] Node: 0[] 24 - 11[V]: Scope: 1[*ast.File] Node: 2[a~(K, V): 1] 28 + 11[V]: Scope: 1[*ast.File] Node: 2[a~(K,V): 1] 25 29 13[d]: Scope: 0[<nil>] Node: 0[] 26 30 14[a]: Scope: 1[*ast.File] Node: 0[1] 27 31 -- pattern.cue -- 32 + @experiment(aliasv2) 33 + 28 34 [string]~X: int 29 35 y: X 30 36 -- out/resolve/pattern -- ··· 34 40 7[y]: Scope: 0[<nil>] Node: 0[] 35 41 8[X]: Scope: 0[<nil>] Node: 0[] 36 42 -- pattern_dual.cue -- 43 + @experiment(aliasv2) 44 + 37 45 [string]~(K, V): int 38 46 y: K 39 47 z: V
+67
cue/ast/astutil/testdata/resolve/redeclared.txtar
··· 1 + # Scenarios that produce alias-redeclaration errors from astutil.Resolve. 2 + # Each .cue file isolates one scenario so out/resolve/errors lists all of 3 + # them in one place. 4 + -- old_label.cue -- 5 + // Old-style label alias on sibling fields. 6 + N=("foo"): 1 7 + N=("bar"): 2 8 + -- postfix_single.cue -- 9 + @experiment(aliasv2) 10 + 11 + // Postfix single-form alias on sibling fields. 12 + a~X: 1 13 + b~X: 2 14 + -- postfix_field.cue -- 15 + @experiment(aliasv2) 16 + 17 + // Postfix dual-form, V (field reference) shared across siblings. 18 + "foo"~(_, V): {a: 1} 19 + "bar"~(_, V): {b: 2} 20 + -- postfix_label.cue -- 21 + @experiment(aliasv2) 22 + 23 + // Postfix dual-form, K (label name capture) shared across siblings. 24 + // 25 + // TODO(https://cuelang.org/issue/4342): this should also report `alias 26 + // "N" redeclared in same scope`, matching the equivalent old-style 27 + // `N=("foo"):` form, but the uniqueness check in astutil/resolve.go 28 + // does not currently see the K binding as let-like, so the second 29 + // declaration silently overrides the first. 30 + "foo"~(N, _): 1 31 + "bar"~(N, _): 2 32 + -- let_clauses.cue -- 33 + // Two let clauses with the same name in the same scope. 34 + top: { 35 + let X = 1 36 + let X = 2 37 + v: X 38 + } 39 + -- let_clauses_top.cue -- 40 + // Two let clauses with the same name at file scope. 41 + let Y = 1 42 + let Y = 2 43 + v: Y 44 + -- alias_field_clash.cue -- 45 + // An alias and a regular field cannot share a name in one scope. 46 + clash: { 47 + let X = 1 48 + X: 2 49 + } 50 + -- out/resolve/errors -- 51 + cannot have both alias and field with name "X" in same scope: 52 + ./alias_field_clash.cue:4:5 53 + alias "X" redeclared in same scope: 54 + ./let_clauses.cue:4:2 55 + alias "Y" redeclared in same scope: 56 + ./let_clauses_top.cue:3:1 57 + alias "N" redeclared in same scope: 58 + ./old_label.cue:3:1 59 + alias "V" redeclared in same scope: 60 + ./postfix_field.cue:5:1 61 + alias "X" redeclared in same scope: 62 + ./postfix_single.cue:5:1 63 + -- out/resolve/postfix_label -- 64 + 3[N]: Scope: 0[<nil>] Node: 0[] 65 + 4[_]: Scope: 0[<nil>] Node: 0[] 66 + 6[N]: Scope: 0[<nil>] Node: 0[] 67 + 7[_]: Scope: 0[<nil>] Node: 0[]