diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index add6512b6..8234ad230 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -14,3 +14,4 @@ - Fixes use of `null` in `sql_table` constraints (ty @landmaj) [#1660](https://github.com/terrastruct/d2/pull/1660) - Fixes elk growing shapes with width/height set [#1679](https://github.com/terrastruct/d2/pull/1679) - Adds a compiler error when accidentally using an arrowhead on a shape [#1686](https://github.com/terrastruct/d2/pull/1686) +- Correctly reports errors from invalid values set by globs. [#1691](https://github.com/terrastruct/d2/pull/1691) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 2c1fe3916..4a51d2457 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -177,7 +177,14 @@ type compiler struct { } func (c *compiler) errorf(n d2ast.Node, f string, v ...interface{}) { - c.err.Errors = append(c.err.Errors, d2parser.Errorf(n, f, v...).(d2ast.Error)) + err := d2parser.Errorf(n, f, v...).(d2ast.Error) + if c.err.ErrorsLookup == nil { + c.err.ErrorsLookup = make(map[d2ast.Error]struct{}) + } + if _, ok := c.err.ErrorsLookup[err]; !ok { + c.err.Errors = append(c.err.Errors, err) + c.err.ErrorsLookup[err] = struct{}{} + } } func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index ac24f6381..70d1ba9e1 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -4241,6 +4241,38 @@ class: { `, "") }, }, + { + name: "double-glob-err-val", + run: func(t *testing.T) { + assertCompile(t, ` +**: { + label: hi + label.near: center +} + +x: { + a -> b +} +`, `d2/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.d2:4:3: invalid "near" field`) + }, + }, + { + name: "double-glob-override-err-val", + run: func(t *testing.T) { + assertCompile(t, ` +(** -> **)[*]: { + label.near: top-center +} +(** -> **)[*]: { + label.near: invalid +} + +x: { + a -> b +} +`, `d2/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.d2:6:2: invalid "near" field`) + }, + }, } for _, tc := range tca { diff --git a/d2ir/compile.go b/d2ir/compile.go index b671f6cd3..9f91c35e4 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -804,7 +804,8 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) { // if already set by a non glob key. func (c *compiler) ignoreLazyGlob(n Node) bool { if c.lazyGlobBeingApplied && n.Primary() != nil { - if n.LastPrimaryRef() != nil { + lastPrimaryRef := n.LastPrimaryRef() + if lastPrimaryRef != nil && !lastPrimaryRef.DueToLazyGlob() { return true } } diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 72bcc116d..23e5aa8f8 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -319,7 +319,7 @@ func (f *Field) Copy(newParent Node) Node { func (f *Field) LastPrimaryRef() Reference { for i := len(f.References) - 1; i >= 0; i-- { - if f.References[i].Primary() && !f.References[i].DueToLazyGlob() { + if f.References[i].Primary() { return f.References[i] } } diff --git a/d2parser/parse.go b/d2parser/parse.go index 3a615cc36..0a6a38d95 100644 --- a/d2parser/parse.go +++ b/d2parser/parse.go @@ -161,7 +161,9 @@ type parser struct { // TODO: rename to Error and make existing Error a private type errorWithRange type ParseError struct { - Errors []d2ast.Error `json:"errs"` + // Errors from globs need to be deduplicated + ErrorsLookup map[d2ast.Error]struct{} `json:"-"` + Errors []d2ast.Error `json:"errs"` } func Errorf(n d2ast.Node, f string, v ...interface{}) error { diff --git a/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.exp.json b/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.exp.json new file mode 100644 index 000000000..31994bb64 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.exp.json @@ -0,0 +1,11 @@ +{ + "graph": null, + "err": { + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.d2,3:2:21-3:20:39", + "errmsg": "d2/testdata/d2compiler/TestCompile2/globs/double-glob-err-val.d2:4:3: invalid \"near\" field" + } + ] + } +} diff --git a/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.exp.json b/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.exp.json new file mode 100644 index 000000000..6059da6a3 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.exp.json @@ -0,0 +1,11 @@ +{ + "graph": null, + "err": { + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.d2,5:1:62-5:20:81", + "errmsg": "d2/testdata/d2compiler/TestCompile2/globs/double-glob-override-err-val.d2:6:2: invalid \"near\" field" + } + ] + } +}