diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 75871506d..36e502a68 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3392,6 +3392,25 @@ z: ${x} assert.Equal(t, 1, len(g.Objects[1].Children)) }, }, + { + name: "spread", + run: func(t *testing.T) { + g := assertCompile(t, ` +vars: { + x: all { + a: b + b: c + } +} +z: { + ...${x} + c +} +`, "") + assert.Equal(t, "z", g.Objects[1].ID) + assert.Equal(t, 3, len(g.Objects[1].Children)) + }, + }, } for _, tc := range tca { @@ -3712,6 +3731,37 @@ hi `, "d2/testdata/d2compiler/TestCompile2/vars/errors/edge.d2:3:3: vars cannot contain an edge") }, }, + { + name: "spread-non-map", + run: func(t *testing.T) { + assertCompile(t, ` +vars: { + x: all +} +z: { + ...${x} + c +} +`, `d2/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.d2:6:3: cannot spread non-map into map`) + }, + }, + { + name: "spread-non-solo", + // NOTE: this doesn't get parsed correctly and so the error message isn't exactly right, but the important thing is that it errors + run: func(t *testing.T) { + assertCompile(t, ` +vars: { + x: { + a: b + } +} +z: { + d: ...${x} + c +} +`, `d2/testdata/d2compiler/TestCompile2/vars/errors/spread-non-solo.d2:8:2: cannot substitute map variable "x" as part of a string`) + }, + }, } for _, tc := range tca { diff --git a/d2ir/compile.go b/d2ir/compile.go index 2c93b6ef4..db1e8ec5c 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -143,14 +143,33 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node Node) { c.errorf(node.LastRef().AST(), `could not resolve variable "%s"`, strings.Join(box.Substitution.IDA(), ".")) return } + if box.Substitution.Spread { + if resolvedField.Composite == nil { + c.errorf(box.Substitution, "cannot spread non-map into map") + continue + } + // TODO arrays + if resolvedField.Map() != nil { + OverlayMap(ParentMap(node), resolvedField.Map()) + } + // Remove the placeholder field + f := node.(*Field) + m := f.parent.(*Map) + for i, f2 := range m.Fields { + if f == f2 { + m.Fields = append(m.Fields[:i], m.Fields[i+1:]...) + break + } + } + } if resolvedField.Primary() == nil { if len(s.Value) > 1 { c.errorf(node.LastRef().AST(), `cannot substitute map variable "%s" as part of a string`, strings.Join(box.Substitution.IDA(), ".")) return } } else { - // If lone and unquoted, replace with value of sub if len(s.Value) == 1 { + // If lone and unquoted, replace with value of sub node.Primary().Value = resolvedField.Primary().Value } else { s.Value[i].String = go2.Pointer(resolvedField.Primary().String()) @@ -255,6 +274,21 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) { ScopeMap: dst, ScopeAST: scopeAST, }) + case n.Substitution != nil: + if !n.Substitution.Spread { + c.errorf(n.Import, "invalid non-spread substitution in map") + continue + } + // placeholder field to be resolved at the end + f := &Field{ + parent: dst, + Primary_: &Scalar{ + Value: &d2ast.UnquotedString{ + Value: []d2ast.InterpolationBox{{Substitution: n.Substitution}}, + }, + }, + } + dst.Fields = append(dst.Fields, f) case n.Import != nil: impn, ok := c._import(n.Import) if !ok { @@ -619,6 +653,7 @@ func (c *compiler) compileArray(dst *Array, a *d2ast.Array, scopeAST *d2ast.Map) irv = n } case *d2ast.Substitution: + // TODO // panic("TODO") } diff --git a/testdata/d2compiler/TestCompile2/vars/basic/spread.exp.json b/testdata/d2compiler/TestCompile2/vars/basic/spread.exp.json new file mode 100644 index 000000000..9dbadf0d4 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/vars/basic/spread.exp.json @@ -0,0 +1,469 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,0:0:0-11:0:62", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,1:0:1-6:1:40", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,1:0:1-1:4:5", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,1:0:1-1:4:5", + "value": [ + { + "string": "vars", + "raw_string": "vars" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,1:6:7-6:1:40", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,2:1:10-5:3:38", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,2:1:10-2:2:11", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,2:1:10-2:2:11", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,2:4:13-2:7:16", + "value": [ + { + "string": "all", + "raw_string": "all" + } + ] + } + }, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,2:8:17-5:3:38", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:2:21-3:6:25", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:2:21-3:3:22", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:2:21-3:3:22", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:5:24-3:6:25", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:4:30-4:8:34", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:4:30-4:5:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:4:30-4:5:31", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:7:33-4:8:34", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:0:41-10:1:61", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:0:41-7:1:42", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:0:41-7:1:42", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:3:44-10:1:61", + "nodes": [ + { + "substitution": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,8:2:48-8:9:55", + "spread": true, + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,8:7:53-8:8:54", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,9:2:58-9:3:59", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,9:2:58-9:3:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,9:2:58-9:3:59", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:2:21-3:3:22", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,3:2:21-3:3:22", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:0:41-7:1:42", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,7:0:41-7:1:42", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,9:2:58-9:3:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,9:2:58-9:3:59", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "vars", + "id_val": "vars", + "attributes": { + "label": { + "value": "vars" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "x", + "id_val": "x", + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:4:30-4:5:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/spread.d2,4:4:30-4:5:31", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/vars/basic/variadic.exp.json b/testdata/d2compiler/TestCompile2/vars/basic/variadic.exp.json new file mode 100644 index 000000000..424de2d0f --- /dev/null +++ b/testdata/d2compiler/TestCompile2/vars/basic/variadic.exp.json @@ -0,0 +1,492 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,0:0:0-11:0:62", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,1:0:1-6:1:40", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,1:0:1-1:4:5", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,1:0:1-1:4:5", + "value": [ + { + "string": "vars", + "raw_string": "vars" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,1:6:7-6:1:40", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,2:1:10-5:3:38", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,2:1:10-2:2:11", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,2:1:10-2:2:11", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,2:4:13-2:7:16", + "value": [ + { + "string": "all", + "raw_string": "all" + } + ] + } + }, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,2:8:17-5:3:38", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:2:21-3:6:25", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:2:21-3:3:22", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:2:21-3:3:22", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:5:24-3:6:25", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:4:30-4:8:34", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:4:30-4:5:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:4:30-4:5:31", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:7:33-4:8:34", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:0:41-10:1:61", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:0:41-7:1:42", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:0:41-7:1:42", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:3:44-10:1:61", + "nodes": [ + { + "substitution": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,8:2:48-8:9:55", + "spread": true, + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,8:7:53-8:8:54", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,9:2:58-9:3:59", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,9:2:58-9:3:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,9:2:58-9:3:59", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:0:41-7:1:42", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,7:0:41-7:1:42", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "\"\"", + "id_val": "", + "attributes": { + "label": { + "value": "all" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:2:21-3:3:22", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,3:2:21-3:3:22", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "vars", + "id_val": "vars", + "attributes": { + "label": { + "value": "vars" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "x", + "id_val": "x", + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:4:30-4:5:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,4:4:30-4:5:31", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,9:2:58-9:3:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/vars/basic/variadic.d2,9:2:58-9:3:59", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.exp.json b/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.exp.json new file mode 100644 index 000000000..02e2b3eb6 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.exp.json @@ -0,0 +1,11 @@ +{ + "graph": null, + "err": { + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.d2,5:2:26-5:9:33", + "errmsg": "d2/testdata/d2compiler/TestCompile2/vars/errors/spread-non-map.d2:6:3: cannot spread non-map into map" + } + ] + } +}