diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index f3c0d2a774..ea1e3ce146 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -3,3 +3,5 @@ #### Improvements 🧹 #### Bugfixes ⛑️ + +- Fixes edge case in compiler using dots in quotes [#1401](https://github.com/terrastruct/d2/pull/1401) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 8c06fd4b32..67edfe1848 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -282,8 +282,8 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { Scope: fr.Context.Scope, } if fr.Context.ScopeMap != nil { - scopeObjIDA := d2ir.BoardIDA(fr.Context.ScopeMap) - r.ScopeObj = obj.Graph.Root.EnsureChildIDVal(scopeObjIDA) + scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context.ScopeMap)) + r.ScopeObj = obj.Graph.Root.EnsureChild(scopeObjIDA) } obj.References = append(obj.References, r) } @@ -635,8 +635,8 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) { Scope: er.Context.Scope, } if er.Context.ScopeMap != nil { - scopeObjIDA := d2ir.BoardIDA(er.Context.ScopeMap) - r.ScopeObj = edge.Src.Graph.Root.EnsureChildIDVal(scopeObjIDA) + scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context.ScopeMap)) + r.ScopeObj = edge.Src.Graph.Root.EnsureChild(scopeObjIDA) } edge.References = append(edge.References, r) } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 56f5b00885..c6fa266bab 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -315,6 +315,20 @@ containers: { `, expErr: `d2/testdata/d2compiler/TestCompile/image_children_Steps.d2:4:3: steps is only allowed at a board root`, }, + { + name: "name-with-dot-underscore", + text: `A: { + _.C +} + +"D.E": { + _.C +} +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, 3, len(g.Objects)) + }, + }, { name: "stroke-width", diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 5043dbb6f3..76046e3773 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -671,38 +671,6 @@ func (obj *Object) HasChild(ids []string) (*Object, bool) { return child, true } -// Keep in sync with EnsureChild. -func (obj *Object) EnsureChildIDVal(ids []string) *Object { - if len(ids) == 0 { - return obj - } - if len(ids) == 1 && ids[0] != "style" { - _, ok := ReservedKeywords[ids[0]] - if ok { - return obj - } - } - - id := ids[0] - ids = ids[1:] - - var child *Object - for _, ch2 := range obj.ChildrenArray { - if ch2.IDVal == id { - child = ch2 - break - } - } - if child == nil { - child = obj.newObject(id) - } - - if len(ids) >= 1 { - return child.EnsureChildIDVal(ids) - } - return child -} - func (obj *Object) HasEdge(mk *d2ast.Key) (*Edge, bool) { ea, ok := obj.FindEdges(mk) if !ok { diff --git a/testdata/d2compiler/TestCompile/name-with-dot-underscore.exp.json b/testdata/d2compiler/TestCompile/name-with-dot-underscore.exp.json new file mode 100644 index 0000000000..7c2ec3cf46 --- /dev/null +++ b/testdata/d2compiler/TestCompile/name-with-dot-underscore.exp.json @@ -0,0 +1,341 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:0:0-7:0:31", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:0:0-2:1:12", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:0:0-0:1:1", + "value": [ + { + "string": "A", + "raw_string": "A" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:3:3-2:1:12", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:2:7-1:5:10", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:2:7-1:5:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:4:9-1:5:10", + "value": [ + { + "string": "C", + "raw_string": "C" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:0:14-6:1:30", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:0:14-4:5:19", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:0:14-4:5:19", + "value": [ + { + "string": "D.E", + "raw_string": "D.E" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:7:21-6:1:30", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:2:25-5:5:28", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:2:25-5:5:28", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:2:25-5:3:26", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:4:27-5:5:28", + "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/TestCompile/name-with-dot-underscore.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,0:0:0-0:1:1", + "value": [ + { + "string": "A", + "raw_string": "A" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "A" + }, + "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/TestCompile/name-with-dot-underscore.d2,1:2:7-1:5:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,1:4:9-1:5:10", + "value": [ + { + "string": "C", + "raw_string": "C" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:2:25-5:5:28", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:2:25-5:3:26", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,5:4:27-5:5:28", + "value": [ + { + "string": "C", + "raw_string": "C" + } + ] + } + } + ] + }, + "key_path_index": 1, + "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": "\"D.E\"", + "id_val": "D.E", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:0:14-4:5:19", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/name-with-dot-underscore.d2,4:0:14-4:5:19", + "value": [ + { + "string": "D.E", + "raw_string": "D.E" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "D.E" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}