From c57d0ee25204d4708bc58b648a77a12123221a5a Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 15:37:07 -0800 Subject: [PATCH 1/7] fix d2oracle --- d2oracle/edit.go | 8 +++++++- d2oracle/edit_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 1d3103a28..9fe1c5389 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -2066,7 +2066,13 @@ func hasSpace(tag string) bool { } func getMostNestedRefs(obj *d2graph.Object) []d2graph.Reference { - most := obj.References[0] + var most d2graph.Reference + for _, ref := range obj.References { + if len(ref.MapKey.Edges) == 0 { + most = ref + break + } + } for _, ref := range obj.References { if len(ref.MapKey.Edges) != 0 { continue diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 02669c453..4c6a16cae 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -2001,6 +2001,32 @@ c: { assert.JSON(t, len(g.Objects), 3) }, }, + { + name: "underscore-connection", + + text: `a: { + b + + _.c.d -> b +} + +c: { + d +} +`, + key: `a.b`, + newKey: `c.b`, + + exp: `a: { + _.c.d -> _.c.b +} + +c: { + d + b +} +`, + }, { name: "flat_middle_container", From 40b4879f47c9780e29cfa09282915d237bb99671 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 16:45:55 -0800 Subject: [PATCH 2/7] fix underscore bug in compiler --- d2compiler/compile_test.go | 7 + d2ir/d2ir.go | 3 +- .../underscore_connection.exp.json | 489 ++++++++++++++ .../TestMove/underscore-connection.exp.json | 624 ++++++++++++++++++ 4 files changed, 1122 insertions(+), 1 deletion(-) create mode 100644 testdata/d2compiler/TestCompile/underscore_connection.exp.json create mode 100644 testdata/d2oracle/TestMove/underscore-connection.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 37e68632c..d31ea2873 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -337,6 +337,13 @@ x: { tassert.Equal(t, g.Objects[0].AbsID(), g.Objects[1].References[0].ScopeObj.AbsID()) }, }, + { + name: "underscore_connection", + text: `a: { + _.c.d -> _.c.b +} +`, + }, { name: "underscore_parent_not_root", diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 455a38707..34ec4ae46 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -770,7 +770,8 @@ func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) { if len(common) > 0 { tmp := *refctx.Edge.Src kp := &tmp - kp.Path = kp.Path[:len(common)] + underscores := countUnderscores(kp.IDA()) + kp.Path = kp.Path[underscores : len(common)+underscores] f, err := m.EnsureField(kp, nil) if err != nil { return nil, err diff --git a/testdata/d2compiler/TestCompile/underscore_connection.exp.json b/testdata/d2compiler/TestCompile/underscore_connection.exp.json new file mode 100644 index 000000000..cdcd84009 --- /dev/null +++ b/testdata/d2compiler/TestCompile/underscore_connection.exp.json @@ -0,0 +1,489 @@ +{ + "graph": { + "name": "", + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:0:0-3:0:24", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:0:0-2:1:23", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:0:0-0:1:1", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:3:3-2:0:22", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:16:21", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:16:21", + "src": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + "edges": [ + { + "index": 0, + "minWidth": 0, + "minHeight": 0, + "label_dimensions": { + "width": 0, + "height": 0 + }, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "a", + "id_val": "a", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.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" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "d", + "id_val": "d", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 2, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "d" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/underscore_connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 2, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2oracle/TestMove/underscore-connection.exp.json b/testdata/d2oracle/TestMove/underscore-connection.exp.json new file mode 100644 index 000000000..46568d214 --- /dev/null +++ b/testdata/d2oracle/TestMove/underscore-connection.exp.json @@ -0,0 +1,624 @@ +{ + "graph": { + "name": "", + "ast": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:0:0-8:0:40", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:0:0-2:1:23", + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:0:0-0:1:1", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:3:3-2:0:22", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:16:21", + "edges": [ + { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:16:21", + "src": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:0:25-7:1:39", + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:0:25-4:1:26", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:0:25-4:1:26", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:3:28-7:0:38", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,5:2:32-5:3:33", + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,5:2:32-5:3:33", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,5:2:32-5:3:33", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,6:2:36-6:3:37", + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,6:2:36-6:3:37", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,6:2:36-6:3:37", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + "edges": [ + { + "index": 0, + "minWidth": 0, + "minHeight": 0, + "label_dimensions": { + "width": 0, + "height": 0 + }, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "a", + "id_val": "a", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.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" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:0:25-4:1:26", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,4:0:25-4:1:26", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "d", + "id_val": "d", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:8:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:2:7-1:3:8", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:4:9-1:5:10", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:6:11-1:7:12", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 2, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,5:2:32-5:3:33", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,5:2:32-5:3:33", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "d" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:10:15-1:16:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:11:16-1:12:17", + "value": [ + { + "string": "_", + "raw_string": "_" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:13:18-1:14:19", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,1:15:20-1:16:21", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 2, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,6:2:36-6:3:37", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestMove/underscore-connection.d2,6:2:36-6:3:37", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": { + "value": "" + } + }, + "zIndex": 0 + } + ] + }, + "err": "" +} From a81ea842cf5e547626bff1668bf3d98b71e39a32 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 16:48:16 -0800 Subject: [PATCH 3/7] add assertion --- d2compiler/compile_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index d31ea2873..9068ad3af 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -343,6 +343,10 @@ x: { _.c.d -> _.c.b } `, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, 3, len(g.Objects)) + tassert.Equal(t, 1, len(g.Edges)) + }, }, { name: "underscore_parent_not_root", From 5a021b8918296b26ed2917dd6e857a2f311db16d Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 16:52:50 -0800 Subject: [PATCH 4/7] oops --- d2compiler/compile_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 9068ad3af..1ed5b18ca 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -344,7 +344,7 @@ x: { } `, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, 3, len(g.Objects)) + tassert.Equal(t, 4, len(g.Objects)) tassert.Equal(t, 1, len(g.Edges)) }, }, From 34b839c7bdc1f1e492bc065fc346f96714694010 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 21:06:57 -0800 Subject: [PATCH 5/7] combine resolveUnderscore and trimCommon --- d2ir/d2ir.go | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 34ec4ae46..a55b1dc3d 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -379,7 +379,7 @@ func (eid *EdgeID) Match(eid2 *EdgeID) bool { return true } -func (eid *EdgeID) resolveUnderscores(m *Map) (*EdgeID, *Map, error) { +func (eid *EdgeID) resolveToCommon(m *Map) (*d2ast.KeyPath, *EdgeID, *Map, error) { eid = eid.Copy() maxUnderscores := go2.Max(countUnderscores(eid.SrcPath), countUnderscores(eid.DstPath)) for i := 0; i < maxUnderscores; i++ { @@ -397,23 +397,21 @@ func (eid *EdgeID) resolveUnderscores(m *Map) (*EdgeID, *Map, error) { } m = ParentMap(m) if m == nil { - return nil, nil, errors.New("invalid underscore") + return nil, nil, nil, errors.New("invalid underscore") } } - return eid, m, nil -} -func (eid *EdgeID) trimCommon() (common []string, _ *EdgeID) { - eid = eid.Copy() + common := &d2ast.KeyPath{} for len(eid.SrcPath) > 1 && len(eid.DstPath) > 1 { if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) { - return common, eid + return common, eid, m, nil } - common = append(common, eid.SrcPath[0]) + common.Path = append(common.Path, d2ast.MakeValueBox(d2ast.RawString(eid.SrcPath[0], true)).StringBox()) eid.SrcPath = eid.SrcPath[1:] eid.DstPath = eid.DstPath[1:] } - return common, eid + + return common, eid, m, nil } type Edge struct { @@ -732,13 +730,12 @@ func (m *Map) DeleteField(ida ...string) *Field { } func (m *Map) GetEdges(eid *EdgeID) []*Edge { - eid, m, err := eid.resolveUnderscores(m) + common, eid, m, err := eid.resolveToCommon(m) if err != nil { return nil } - common, eid := eid.trimCommon() - if len(common) > 0 { - f := m.GetField(common...) + if len(common.Path) > 0 { + f := m.GetField(common.IDA()...) if f == nil { return nil } @@ -762,17 +759,12 @@ func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) { return nil, d2parser.Errorf(refctx.Edge, "cannot create edge inside edge") } - eid, m, err := eid.resolveUnderscores(m) + common, eid, m, err := eid.resolveToCommon(m) if err != nil { return nil, d2parser.Errorf(refctx.Edge, err.Error()) } - common, eid := eid.trimCommon() - if len(common) > 0 { - tmp := *refctx.Edge.Src - kp := &tmp - underscores := countUnderscores(kp.IDA()) - kp.Path = kp.Path[underscores : len(common)+underscores] - f, err := m.EnsureField(kp, nil) + if len(common.Path) > 0 { + f, err := m.EnsureField(common, nil) if err != nil { return nil, err } From b41baddcee46bee4c68d2276b95f128a93ccba31 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 21:26:29 -0800 Subject: [PATCH 6/7] pr comments --- d2ir/d2ir.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index a55b1dc3d..9f37917e3 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -379,7 +379,9 @@ func (eid *EdgeID) Match(eid2 *EdgeID) bool { return true } -func (eid *EdgeID) resolveToCommon(m *Map) (*d2ast.KeyPath, *EdgeID, *Map, error) { +// resolve resolves both underscores and commons in eid. +// It returns the new eid, containing map adjusted for underscores and common ida. +func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []string, _ error) { eid = eid.Copy() maxUnderscores := go2.Max(countUnderscores(eid.SrcPath), countUnderscores(eid.DstPath)) for i := 0; i < maxUnderscores; i++ { @@ -401,17 +403,16 @@ func (eid *EdgeID) resolveToCommon(m *Map) (*d2ast.KeyPath, *EdgeID, *Map, error } } - common := &d2ast.KeyPath{} for len(eid.SrcPath) > 1 && len(eid.DstPath) > 1 { if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) { - return common, eid, m, nil + return eid, m, common, nil } - common.Path = append(common.Path, d2ast.MakeValueBox(d2ast.RawString(eid.SrcPath[0], true)).StringBox()) + common = append(common, eid.SrcPath[0]) eid.SrcPath = eid.SrcPath[1:] eid.DstPath = eid.DstPath[1:] } - return common, eid, m, nil + return eid, m, common, nil } type Edge struct { @@ -730,12 +731,12 @@ func (m *Map) DeleteField(ida ...string) *Field { } func (m *Map) GetEdges(eid *EdgeID) []*Edge { - common, eid, m, err := eid.resolveToCommon(m) + eid, m, common, err := eid.resolve(m) if err != nil { return nil } - if len(common.Path) > 0 { - f := m.GetField(common.IDA()...) + if len(common) > 0 { + f := m.GetField(common...) if f == nil { return nil } @@ -759,12 +760,12 @@ func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) { return nil, d2parser.Errorf(refctx.Edge, "cannot create edge inside edge") } - common, eid, m, err := eid.resolveToCommon(m) + eid, m, common, err := eid.resolve(m) if err != nil { return nil, d2parser.Errorf(refctx.Edge, err.Error()) } - if len(common.Path) > 0 { - f, err := m.EnsureField(common, nil) + if len(common) > 0 { + f, err := m.EnsureField(d2ast.MakeKeyPath(common), nil) if err != nil { return nil, err } From e308d6de3902573e63739f0dc11d8daf6aa45b95 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 21:34:07 -0800 Subject: [PATCH 7/7] changelog --- ci/release/changelogs/next.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index ec361c8e5..f343941be 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -5,3 +5,4 @@ #### Bugfixes ⛑️ - Fixes edge case where layouts with dagre show a connection from the bottom side of shapes being slightly disconnected from the shape. [#820](https://github.com/terrastruct/d2/pull/820) +- Fixes rare compiler bug when using underscores in edges to create objects across containers. [#824](https://github.com/terrastruct/d2/pull/824)