From 0d9328b9e5587e1a00606d4f0390680d44bef020 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Thu, 8 Feb 2024 22:21:56 -0800 Subject: [PATCH] fix nested connection implicit delete --- ci/release/changelogs/next.md | 1 + d2compiler/compile_test.go | 11 + d2ir/d2ir.go | 17 +- .../delete-nested-connection.exp.json | 265 ++++++++++++++++++ 4 files changed, 289 insertions(+), 5 deletions(-) create mode 100644 testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.exp.json diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 2d39449f07..f3a19c9711 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -4,4 +4,5 @@ #### Bugfixes ⛑️ +- Fixes `null` being set on a nested shape not working in certain cases when connections also pointed to that shape [1830](https://github.com/terrastruct/d2/pull/1830) - Fixes edge case of bad import syntax crashing using d2 as a library [1829](https://github.com/terrastruct/d2/pull/1829) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index c743989341..8e23040499 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3239,6 +3239,17 @@ y: null assert.Equal(t, 0, len(g.Edges)) }, }, + { + name: "delete-nested-connection", + run: func(t *testing.T) { + g, _ := assertCompile(t, ` +a -> b.c +b.c: null +`, "") + assert.Equal(t, 2, len(g.Objects)) + assert.Equal(t, 0, len(g.Edges)) + }, + }, { name: "delete-multiple-connections", run: func(t *testing.T) { diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 5a21c549e6..227fa69f9b 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -950,13 +950,20 @@ func (m *Map) DeleteField(ida ...string) *Field { } if len(rest) == 0 { for _, fr := range f.References { - for _, e := range m.Edges { - for _, er := range e.References { - if er.Context_ == fr.Context_ { - m.DeleteEdge(e.ID) - break + currM := m + for currM != nil { + for _, e := range currM.Edges { + for _, er := range e.References { + if er.Context_ == fr.Context_ { + currM.DeleteEdge(e.ID) + break + } } } + if NodeBoardKind(currM) != "" { + break + } + currM = ParentMap(currM) } } m.Fields = append(m.Fields[:i], m.Fields[i+1:]...) diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.exp.json new file mode 100644 index 0000000000..ab4289ac1d --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.exp.json @@ -0,0 +1,265 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,0:0:0-3:0:20", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:0:1-1:8:9", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:0:1-1:8:9", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:5:6-1:8:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:7:8-1:8:9", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:0:10-2:9:19", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:0:10-2:3:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:0:10-2:1:11", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:2:12-2:3:13", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:5:15-2:9:19" + } + } + } + } + ] + }, + "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/nulls/implicit/delete-nested-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "a" + }, + "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/nulls/implicit/delete-nested-connection.d2,1:5:6-1:8:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,1:7:8-1:8:9", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:0:10-2:3:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:0:10-2:1:11", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-nested-connection.d2,2:2:12-2:3:13", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "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 + } + ] + }, + "err": null +}