From 48bb6df3fe9f1bc71dd409eb40adbbe6414bbc82 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Thu, 15 Jun 2023 17:39:05 -0700 Subject: [PATCH 01/12] save --- d2compiler/compile.go | 10 +- d2compiler/compile_test.go | 70 ++++++++ d2graph/d2graph.go | 33 ++++ .../TestCompile2/nulls/basic/shape.exp.json | 87 ++++++++++ .../nulls/null/basic-shape.exp.json | 153 ++++++++++++++++++ .../nulls/reappear/shape.exp.json | 110 +++++++++++++ 6 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 testdata/d2compiler/TestCompile2/nulls/basic/shape.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/null/basic-shape.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 3094e08199..f4630137cc 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -250,6 +250,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { } func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { + println("\033[1;31m--- DEBUG:", "=======================", "\033[m") keyword := strings.ToLower(f.Name) _, isStyleReserved := d2graph.StyleKeywords[keyword] if isStyleReserved { @@ -303,7 +304,13 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { } } + if f.Primary() != nil { + if _, ok := f.Primary().Value.(*d2ast.Null); ok { + return + } + } obj = obj.EnsureChild(d2graphIDA([]string{f.Name})) + if f.Primary() != nil { c.compileLabel(&obj.Attributes, f) } @@ -340,9 +347,6 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { func (c *compiler) compileLabel(attrs *d2graph.Attributes, f d2ir.Node) { scalar := f.Primary().Value switch scalar := scalar.(type) { - case *d2ast.Null: - // TODO: Delete instead. - attrs.Label.Value = scalar.ScalarString() case *d2ast.BlockString: if strings.TrimSpace(scalar.ScalarString()) == "" { c.errorf(f.LastPrimaryKey(), "block string cannot be empty") diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index c6cea1b2f8..1101e479ce 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2743,6 +2743,7 @@ func TestCompile2(t *testing.T) { t.Run("boards", testBoards) t.Run("seqdiagrams", testSeqDiagrams) + t.Run("nulls", testNulls) } func testBoards(t *testing.T) { @@ -2923,6 +2924,75 @@ Office chatter: { }) } +func testNulls(t *testing.T) { + t.Parallel() + + t.Run("basic", func(t *testing.T) { + t.Parallel() + + tca := []struct { + name string + skip bool + run func(t *testing.T) + }{ + { + name: "shape", + run: func(t *testing.T) { + g := assertCompile(t, ` +a +a: null +`, "") + assert.Equal(t, 0, len(g.Objects)) + }, + }, + } + + for _, tc := range tca { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.skip { + t.SkipNow() + } + tc.run(t) + }) + } + }) + + t.Run("reappear", func(t *testing.T) { + t.Parallel() + + tca := []struct { + name string + skip bool + run func(t *testing.T) + }{ + { + name: "shape", + run: func(t *testing.T) { + g := assertCompile(t, ` +a +a: null +a +`, "") + assert.Equal(t, 1, len(g.Objects)) + }, + }, + } + + for _, tc := range tca { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.skip { + t.SkipNow() + } + tc.run(t) + }) + } + }) +} + func assertCompile(t *testing.T, text string, expErr string) *d2graph.Graph { d2Path := fmt.Sprintf("d2/testdata/d2compiler/%v.d2", t.Name()) g, err := d2compiler.Compile(d2Path, strings.NewReader(text), nil) diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index eb47de274f..27773d75a3 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -785,6 +785,39 @@ func (obj *Object) ensureChildEdge(ida []string) *Object { return obj } +// DeleteChild deletes a child from the graph. +// If it has connections or children, those will also be deleted (recursively) +// func (obj *Object) DeleteChild(ida []string) error { +// if len(ida) == 0 { +// return nil +// } +// +// _, is := ReservedKeywordHolders[ida[0]] +// if len(ida) == 1 && !is { +// _, ok := ReservedKeywords[ida[0]] +// if ok { +// return obj +// } +// } +// +// id := ida[0] +// ida = ida[1:] +// +// if id == "_" { +// return obj.Parent.EnsureChild(ida) +// } +// +// child, ok := obj.Children[strings.ToLower(id)] +// if !ok { +// child = obj.newObject(id) +// } +// +// if len(ida) >= 1 { +// return child.EnsureChild(ida) +// } +// return child +// } + // EnsureChild grabs the child by ids or creates it if it does not exist including all // intermediate nodes. func (obj *Object) EnsureChild(ida []string) *Object { diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/shape.exp.json new file mode 100644 index 0000000000..4f2c2fd5ce --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/basic/shape.exp.json @@ -0,0 +1,87 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,0:0:0-3:0:11", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,1:0:1-1:1:2", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,2:0:3-2:7:10", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,2:0:3-2:1:4", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/shape.d2,2:3:6-2:7:10" + } + } + } + } + ] + }, + "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": null + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.exp.json new file mode 100644 index 0000000000..f7b8729849 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.exp.json @@ -0,0 +1,153 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,0:0:0-3:0:11", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,1:0:1-1:1:2", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:0:3-2:7:10", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:0:3-2:1:4", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:3:6-2:7:10" + } + } + } + } + ] + }, + "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/null/basic-shape.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/null/basic-shape.d2,2:0:3-2:1:4", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "" + }, + "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/nulls/reappear/shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json new file mode 100644 index 0000000000..ebeb96548e --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json @@ -0,0 +1,110 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,0:0:0-4:0:13", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:7:10", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:3:6-2:7:10" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "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": null + }, + "err": null +} From 6749115ce241047dca9a96705b1a6b6be3ca0c6b Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 25 Jun 2023 18:59:53 -0700 Subject: [PATCH 02/12] reappear works --- d2compiler/compile.go | 1 - d2ir/compile.go | 7 ++ .../nulls/reappear/shape.exp.json | 88 ++++++++++++++++++- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index f4630137cc..fceec752d2 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -250,7 +250,6 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { } func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { - println("\033[1;31m--- DEBUG:", "=======================", "\033[m") keyword := strings.ToLower(f.Name) _, isStyleReserved := d2graph.StyleKeywords[keyword] if isStyleReserved { diff --git a/d2ir/compile.go b/d2ir/compile.go index 20a03b103e..7c5ed5fb08 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -156,6 +156,13 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext) return } + if f.Primary() != nil { + // null only applies if it's the appearance + if _, ok := f.Primary().Value.(*d2ast.Null); ok { + f.Primary_ = nil + } + } + if refctx.Key.Primary.Unbox() != nil { f.Primary_ = &Scalar{ parent: f, diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json index ebeb96548e..cd14b31742 100644 --- a/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json @@ -104,7 +104,93 @@ "zIndex": 0 }, "edges": null, - "objects": null + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", + "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 + } + ] }, "err": null } From 757f292a20e8401e64719f650e224d7be41735d4 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 25 Jun 2023 20:35:56 -0700 Subject: [PATCH 03/12] edge works --- d2compiler/compile.go | 5 + d2compiler/compile_test.go | 10 + .../TestCompile2/nulls/basic/edge.exp.json | 269 ++++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index fceec752d2..2486567f9e 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -709,6 +709,11 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) { } func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) { + if e.Primary() != nil { + if _, ok := e.Primary().Value.(*d2ast.Null); ok { + return + } + } edge, err := obj.Connect(d2graphIDA(e.ID.SrcPath), d2graphIDA(e.ID.DstPath), e.ID.SrcArrow, e.ID.DstArrow, "") if err != nil { c.errorf(e.References[0].AST(), err.Error()) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 1101e479ce..82fd3f19c0 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2945,6 +2945,16 @@ a: null assert.Equal(t, 0, len(g.Objects)) }, }, + { + name: "edge", + run: func(t *testing.T) { + g := assertCompile(t, ` +a -> b +(a -> b)[0]: null +`, "") + assert.Equal(t, 0, len(g.Edges)) + }, + }, } for _, tc := range tca { diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json new file mode 100644 index 0000000000..9f83b57fc3 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json @@ -0,0 +1,269 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,0:0:0-3:0:26", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:0:8-2:17:25", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:7:15", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:8:16-2:11:19", + "int": 0, + "glob": false + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:13:21-2:17:25" + } + } + } + } + ] + }, + "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/basic/edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "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/basic/edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} From 09d1ec63148c71a7841b861985758e0c94f88cac Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 25 Jun 2023 23:10:56 -0700 Subject: [PATCH 04/12] reimplement --- d2compiler/compile.go | 19 ++- d2compiler/compile_test.go | 33 ++++ d2graph/d2graph.go | 59 +++---- d2ir/compile.go | 8 +- d2ir/d2ir.go | 14 ++ .../TestCompile2/nulls/basic/edge.exp.json | 133 +-------------- .../nulls/implicit/connection.exp.json | 156 ++++++++++++++++++ .../nulls/reappear/shape.exp.json | 2 +- 8 files changed, 244 insertions(+), 180 deletions(-) create mode 100644 testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 2486567f9e..581c1beb5b 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -78,6 +78,7 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph { ir = ir.Copy(nil).(*d2ir.Map) // c.preprocessSeqDiagrams(ir) c.compileMap(g.Root, ir) + c.nullify(g) if len(c.err.Errors) == 0 { c.validateKeys(g.Root, ir) } @@ -244,7 +245,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { } for _, e := range m.Edges { - c.compileEdge(obj, e) + c.compileEdge(obj, e, m) } } } @@ -303,11 +304,6 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { } } - if f.Primary() != nil { - if _, ok := f.Primary().Value.(*d2ast.Null); ok { - return - } - } obj = obj.EnsureChild(d2graphIDA([]string{f.Name})) if f.Primary() != nil { @@ -708,12 +704,13 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) { } } -func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) { +func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge, m *d2ir.Map) { if e.Primary() != nil { if _, ok := e.Primary().Value.(*d2ast.Null); ok { return } } + edge, err := obj.Connect(d2graphIDA(e.ID.SrcPath), d2graphIDA(e.ID.DstPath), e.ID.SrcArrow, e.ID.DstArrow, "") if err != nil { c.errorf(e.References[0].AST(), err.Error()) @@ -844,6 +841,14 @@ func (c *compiler) compileArrowheads(edge *d2graph.Edge, f *d2ir.Field) { } } +func (c *compiler) nullify(g *d2graph.Graph) { + for _, obj := range g.Objects { + if len(obj.References) > 0 && obj.References[len(obj.References)-1].Nulled() { + g.DeleteObject(obj) + } + } +} + // TODO add more, e.g. C, bash var ShortToFullLanguageAliases = map[string]string{ "md": "markdown", diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 82fd3f19c0..9ce23f5bf2 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3001,6 +3001,39 @@ a }) } }) + + t.Run("implicit", func(t *testing.T) { + t.Parallel() + + tca := []struct { + name string + skip bool + run func(t *testing.T) + }{ + { + name: "connection", + run: func(t *testing.T) { + g := assertCompile(t, ` +x -> y +y: null +`, "") + assert.Equal(t, 1, len(g.Objects)) + assert.Equal(t, 0, len(g.Edges)) + }, + }, + } + + for _, tc := range tca { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.skip { + t.SkipNow() + } + tc.run(t) + }) + } + }) } func assertCompile(t *testing.T, text string, expErr string) *d2graph.Graph { diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 27773d75a3..f86eb8f4e9 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -73,6 +73,28 @@ func (g *Graph) RootBoard() *Graph { return g } +// DeleteObject deletes an object along with all its descendants. +// It also deletes all edges connected to it or a descendant. +func (g *Graph) DeleteObject(obj *Object) { + for i, obj2 := range g.Objects { + if obj == obj2 { + g.Objects = append(g.Objects[:i], g.Objects[i+1:]...) + i-- + } + } + obj.Parent.removeChild(obj) + + for i, e := range g.Edges { + if e.Src == obj || e.Dst == obj { + g.Edges = append(g.Edges[:i], g.Edges[i+1:]...) + } + } + + for _, ch := range obj.ChildrenArray { + g.DeleteObject(ch) + } +} + type LayoutGraph func(context.Context, *Graph) error // TODO consider having different Scalar types @@ -193,6 +215,10 @@ type Reference struct { ScopeAST *d2ast.Map `json:"-"` } +func (r *Reference) Nulled() bool { + return r.MapKey != nil && r.MapKey.Value.Null != nil +} + func (r Reference) MapKeyEdgeDest() bool { return r.Key == r.MapKey.Edges[r.MapKeyEdgeIndex].Dst } @@ -785,39 +811,6 @@ func (obj *Object) ensureChildEdge(ida []string) *Object { return obj } -// DeleteChild deletes a child from the graph. -// If it has connections or children, those will also be deleted (recursively) -// func (obj *Object) DeleteChild(ida []string) error { -// if len(ida) == 0 { -// return nil -// } -// -// _, is := ReservedKeywordHolders[ida[0]] -// if len(ida) == 1 && !is { -// _, ok := ReservedKeywords[ida[0]] -// if ok { -// return obj -// } -// } -// -// id := ida[0] -// ida = ida[1:] -// -// if id == "_" { -// return obj.Parent.EnsureChild(ida) -// } -// -// child, ok := obj.Children[strings.ToLower(id)] -// if !ok { -// child = obj.newObject(id) -// } -// -// if len(ida) >= 1 { -// return child.EnsureChild(ida) -// } -// return child -// } - // EnsureChild grabs the child by ids or creates it if it does not exist including all // intermediate nodes. func (obj *Object) EnsureChild(ida []string) *Object { diff --git a/d2ir/compile.go b/d2ir/compile.go index 7c5ed5fb08..be97b62f23 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -156,18 +156,12 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext) return } - if f.Primary() != nil { - // null only applies if it's the appearance - if _, ok := f.Primary().Value.(*d2ast.Null); ok { - f.Primary_ = nil - } - } - if refctx.Key.Primary.Unbox() != nil { f.Primary_ = &Scalar{ parent: f, Value: refctx.Key.Primary.Unbox(), } + } if refctx.Key.Value.Array != nil { a := &Array{ diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 7234256f76..4ff2ddac4e 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -786,6 +786,20 @@ func (m *Map) GetEdges(eid *EdgeID) []*Edge { return ea } +func (m *Map) DeleteEdge(eid *EdgeID) *Edge { + if eid == nil { + return nil + } + + for i, e := range m.Edges { + if e.ID.Match(eid) { + m.Edges = append(m.Edges[:i], m.Edges[i+1:]...) + return e + } + } + return nil +} + func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) { if ParentEdge(m) != nil { return nil, d2parser.Errorf(refctx.Edge, "cannot create edge inside edge") diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json index 9f83b57fc3..842a64237a 100644 --- a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json @@ -132,138 +132,7 @@ "zIndex": 0 }, "edges": null, - "objects": [ - { - "id": "a", - "id_val": "a", - "references": [ - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", - "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/basic/edge.d2,1:5:6-1:6:7", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7", - "value": [ - { - "string": "b", - "raw_string": "b" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", - "value": [ - { - "string": "b", - "raw_string": "b" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 - } - ], - "attributes": { - "label": { - "value": "b" - }, - "labelDimensions": { - "width": 0, - "height": 0 - }, - "style": {}, - "near_key": null, - "shape": { - "value": "rectangle" - }, - "direction": { - "value": "" - }, - "constraint": null - }, - "zIndex": 0 - } - ] + "objects": null }, "err": null } diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json new file mode 100644 index 0000000000..bfead385b4 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json @@ -0,0 +1,156 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,0:0:0-3:0:16", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:5:6-1:6:7", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:7:15", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:1:9", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:3:11-2:7:15" + } + } + } + } + ] + }, + "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": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "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/nulls/reappear/shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json index cd14b31742..e8a97f7703 100644 --- a/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json @@ -172,7 +172,7 @@ ], "attributes": { "label": { - "value": "a" + "value": "" }, "labelDimensions": { "width": 0, From e1eecf7c7baa63a5b75ee83a98bbdd3eed166845 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 25 Jun 2023 23:11:47 -0700 Subject: [PATCH 05/12] reimplement --- d2compiler/compile_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 9ce23f5bf2..1dc1ccc5b4 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3011,7 +3011,7 @@ a run func(t *testing.T) }{ { - name: "connection", + name: "delete-connection", run: func(t *testing.T) { g := assertCompile(t, ` x -> y @@ -3021,6 +3021,17 @@ y: null assert.Equal(t, 0, len(g.Edges)) }, }, + { + name: "no-delete-connection", + run: func(t *testing.T) { + g := assertCompile(t, ` +y: null +x -> y +`, "") + assert.Equal(t, 2, len(g.Objects)) + assert.Equal(t, 1, len(g.Edges)) + }, + }, } for _, tc := range tca { From 02fa36d5986b986756a74f59f710e212b5c21fc3 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 10:36:12 -0700 Subject: [PATCH 06/12] save --- d2compiler/compile_test.go | 26 ++ .../nulls/implicit/delete-children.exp.json | 291 +++++++++++++ .../nulls/implicit/delete-connection.exp.json | 156 +++++++ .../implicit/no-delete-connection.exp.json | 252 ++++++++++++ .../TestCompile2/nulls/reappear/edge.exp.json | 386 ++++++++++++++++++ 5 files changed, 1111 insertions(+) create mode 100644 testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 1dc1ccc5b4..34e9f3f20d 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2952,6 +2952,7 @@ a: null a -> b (a -> b)[0]: null `, "") + assert.Equal(t, 2, len(g.Objects)) assert.Equal(t, 0, len(g.Edges)) }, }, @@ -2988,6 +2989,18 @@ a assert.Equal(t, 1, len(g.Objects)) }, }, + { + name: "edge", + run: func(t *testing.T) { + g := assertCompile(t, ` +a -> b +(a -> b)[0]: null +a -> b +`, "") + assert.Equal(t, 2, len(g.Objects)) + assert.Equal(t, 1, len(g.Edges)) + }, + }, } for _, tc := range tca { @@ -3032,6 +3045,19 @@ x -> y assert.Equal(t, 1, len(g.Edges)) }, }, + { + name: "delete-children", + run: func(t *testing.T) { + g := assertCompile(t, ` +x.y.z +a.b.c + +x: null +a.b: null +`, "") + assert.Equal(t, 1, len(g.Objects)) + }, + }, } for _, tc := range tca { diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json new file mode 100644 index 0000000000..758fbbabb3 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json @@ -0,0 +1,291 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,0:0:0-6:0:32", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,1:0:1-1:5:6", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,1:0:1-1:5:6", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,1:2:3-1:3:4", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,1:4:5-1:5:6", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:0:7-2:5:12", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:0:7-2:5:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:0:7-2:1:8", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:2:9-2:3:10", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:4:11-2:5:12", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,4:0:14-4:7:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,4:0:14-4:1:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,4:0:14-4:1:15", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,4:3:17-4:7:21" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:9:31", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:3:25", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:1:23", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:2:24-5:3:25", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:5:27-5:9:31" + } + } + } + } + ] + }, + "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-children.d2,2:0:7-2:5:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:0:7-2:1:8", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:2:9-2:3:10", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,2:4:11-2:5:12", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:3:25", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:1:23", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:2:24-5:3:25", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "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 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.exp.json new file mode 100644 index 0000000000..62151696bc --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.exp.json @@ -0,0 +1,156 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,0:0:0-3:0:16", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:5:6-1:6:7", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,2:0:8-2:7:15", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,2:0:8-2:1:9", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,2:3:11-2:7:15" + } + } + } + } + ] + }, + "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": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "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/nulls/implicit/no-delete-connection.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json new file mode 100644 index 0000000000..b7d4840b6a --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json @@ -0,0 +1,252 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,0:0:0-3:0:16", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:7:8", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:3:4-1:7:8" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:6:15", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:6:15", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "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": [ + { + "index": 0, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "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/nulls/reappear/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json new file mode 100644 index 0000000000..21b5842150 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json @@ -0,0 +1,386 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,0:0:0-4:0:33", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:0:8-2:17:25", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:7:15", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:8:16-2:11:19", + "int": 0, + "glob": false + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:13:21-2:17:25" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:6:32", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:6:32", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:1:27", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:1:27", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:5:31-3:6:32", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:5:31-3:6:32", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "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": [ + { + "index": 0, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:1:27", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:1:27", + "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/reappear/edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:5:31-3:6:32", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:5:31-3:6:32", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} From 5be1f6c187628265606017a43cb89bf465621555 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 10:39:38 -0700 Subject: [PATCH 07/12] cleanup --- d2compiler/compile.go | 11 ++--------- d2ir/compile.go | 1 - d2ir/d2ir.go | 14 -------------- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 581c1beb5b..27f12ed281 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -245,7 +245,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { } for _, e := range m.Edges { - c.compileEdge(obj, e, m) + c.compileEdge(obj, e) } } } @@ -305,7 +305,6 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { } obj = obj.EnsureChild(d2graphIDA([]string{f.Name})) - if f.Primary() != nil { c.compileLabel(&obj.Attributes, f) } @@ -704,13 +703,7 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) { } } -func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge, m *d2ir.Map) { - if e.Primary() != nil { - if _, ok := e.Primary().Value.(*d2ast.Null); ok { - return - } - } - +func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) { edge, err := obj.Connect(d2graphIDA(e.ID.SrcPath), d2graphIDA(e.ID.DstPath), e.ID.SrcArrow, e.ID.DstArrow, "") if err != nil { c.errorf(e.References[0].AST(), err.Error()) diff --git a/d2ir/compile.go b/d2ir/compile.go index be97b62f23..20a03b103e 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -161,7 +161,6 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext) parent: f, Value: refctx.Key.Primary.Unbox(), } - } if refctx.Key.Value.Array != nil { a := &Array{ diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 4ff2ddac4e..7234256f76 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -786,20 +786,6 @@ func (m *Map) GetEdges(eid *EdgeID) []*Edge { return ea } -func (m *Map) DeleteEdge(eid *EdgeID) *Edge { - if eid == nil { - return nil - } - - for i, e := range m.Edges { - if e.ID.Match(eid) { - m.Edges = append(m.Edges[:i], m.Edges[i+1:]...) - return e - } - } - return nil -} - func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) { if ParentEdge(m) != nil { return nil, d2parser.Errorf(refctx.Edge, "cannot create edge inside edge") From 905a9317a2432beac987c6dba97c714fe67b0c42 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 10:51:07 -0700 Subject: [PATCH 08/12] fix --- d2compiler/compile.go | 5 + d2graph/d2graph.go | 15 +- .../TestCompile2/nulls/basic/edge.exp.json | 133 +++++++++++++++++- .../TestCompile2/nulls/reappear/edge.exp.json | 2 +- 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 27f12ed281..d75ceb2f9c 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -840,6 +840,11 @@ func (c *compiler) nullify(g *d2graph.Graph) { g.DeleteObject(obj) } } + for _, e := range g.Edges { + if len(e.References) > 0 && e.References[len(e.References)-1].Nulled() { + g.DeleteEdge(e) + } + } } // TODO add more, e.g. C, bash diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index f86eb8f4e9..e140542f11 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -95,6 +95,15 @@ func (g *Graph) DeleteObject(obj *Object) { } } +func (g *Graph) DeleteEdge(e *Edge) { + for i, e2 := range g.Edges { + if e == e2 { + g.Edges = append(g.Edges[:i], g.Edges[i+1:]...) + i-- + } + } +} + type LayoutGraph func(context.Context, *Graph) error // TODO consider having different Scalar types @@ -216,7 +225,7 @@ type Reference struct { } func (r *Reference) Nulled() bool { - return r.MapKey != nil && r.MapKey.Value.Null != nil + return r.MapKey != nil && len(r.MapKey.Edges) == 0 && r.MapKey.Value.Null != nil } func (r Reference) MapKeyEdgeDest() bool { @@ -1146,6 +1155,10 @@ type EdgeReference struct { ScopeAST *d2ast.Map `json:"-"` } +func (er *EdgeReference) Nulled() bool { + return er.MapKey != nil && er.MapKey.Value.Null != nil +} + func (e *Edge) GetAstEdge() *d2ast.Edge { return e.References[0].Edge } diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json index 842a64237a..9f83b57fc3 100644 --- a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json @@ -132,7 +132,138 @@ "zIndex": 0 }, "edges": null, - "objects": null + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", + "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/basic/edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "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/nulls/reappear/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json index 21b5842150..726082f0ec 100644 --- a/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json @@ -179,7 +179,7 @@ }, "edges": [ { - "index": 0, + "index": 1, "isCurve": false, "src_arrow": false, "dst_arrow": true, From 1acc3d685a36b3d0c538d9ab17eccd656b835e59 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 11:57:18 -0700 Subject: [PATCH 09/12] new implementation --- d2compiler/compile.go | 14 - d2compiler/compile_test.go | 82 +++++ d2graph/d2graph.go | 8 - d2ir/compile.go | 9 + d2ir/d2ir.go | 25 ++ .../TestCompile2/nulls/basic/edge.exp.json | 40 --- .../nulls/implicit/delete-children.exp.json | 31 -- .../implicit/no-delete-connection.exp.json | 48 +-- .../nulls/multiboard/scenario.exp.json | 226 +++++++++++++ .../nulls/reappear/attribute-reset.exp.json | 184 +++++++++++ .../nulls/reappear/children-reset.exp.json | 309 ++++++++++++++++++ .../nulls/reappear/edge-reset.exp.json | 224 +++++++++++++ .../TestCompile2/nulls/reappear/edge.exp.json | 42 +-- .../nulls/reappear/reset.exp.json | 184 +++++++++++ .../nulls/reappear/shape.exp.json | 42 +-- 15 files changed, 1259 insertions(+), 209 deletions(-) create mode 100644 testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.exp.json create mode 100644 testdata/d2compiler/TestCompile2/nulls/reappear/reset.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index d75ceb2f9c..fdb24e5513 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -78,7 +78,6 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph { ir = ir.Copy(nil).(*d2ir.Map) // c.preprocessSeqDiagrams(ir) c.compileMap(g.Root, ir) - c.nullify(g) if len(c.err.Errors) == 0 { c.validateKeys(g.Root, ir) } @@ -834,19 +833,6 @@ func (c *compiler) compileArrowheads(edge *d2graph.Edge, f *d2ir.Field) { } } -func (c *compiler) nullify(g *d2graph.Graph) { - for _, obj := range g.Objects { - if len(obj.References) > 0 && obj.References[len(obj.References)-1].Nulled() { - g.DeleteObject(obj) - } - } - for _, e := range g.Edges { - if len(e.References) > 0 && e.References[len(e.References)-1].Nulled() { - g.DeleteEdge(e) - } - } -} - // TODO add more, e.g. C, bash var ShortToFullLanguageAliases = map[string]string{ "md": "markdown", diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 34e9f3f20d..db89c23199 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2956,6 +2956,16 @@ a -> b assert.Equal(t, 0, len(g.Edges)) }, }, + // { + // name: "attribute", + // run: func(t *testing.T) { + // g := assertCompile(t, ` + // a.style.opacity: 0.2 + // a.style.opacity: null + // `, "") + // assert.Equal(t, "0.2", g.Objects[0].Attributes.Style.Opacity.Value) + // }, + // }, } for _, tc := range tca { @@ -3001,6 +3011,41 @@ a -> b assert.Equal(t, 1, len(g.Edges)) }, }, + { + name: "attribute-reset", + run: func(t *testing.T) { + g := assertCompile(t, ` +a.style.opacity: 0.2 +a: null +a +`, "") + assert.Equal(t, 1, len(g.Objects)) + assert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[0].Attributes.Style.Opacity) + }, + }, + { + name: "edge-reset", + run: func(t *testing.T) { + g := assertCompile(t, ` +a -> b +a: null +a +`, "") + assert.Equal(t, 2, len(g.Objects)) + assert.Equal(t, 0, len(g.Edges)) + }, + }, + { + name: "children-reset", + run: func(t *testing.T) { + g := assertCompile(t, ` +a.b.c +a.b: null +a.b +`, "") + assert.Equal(t, 2, len(g.Objects)) + }, + }, } for _, tc := range tca { @@ -3071,6 +3116,43 @@ a.b: null }) } }) + + t.Run("multiboard", func(t *testing.T) { + t.Parallel() + + tca := []struct { + name string + skip bool + run func(t *testing.T) + }{ + { + name: "scenario", + run: func(t *testing.T) { + g := assertCompile(t, ` +x + +scenarios: { + a: { + x: null + } +} +`, "") + assert.Equal(t, 0, len(g.Scenarios[0].Objects)) + }, + }, + } + + for _, tc := range tca { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.skip { + t.SkipNow() + } + tc.run(t) + }) + } + }) } func assertCompile(t *testing.T, text string, expErr string) *d2graph.Graph { diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index e140542f11..9feb43fdaf 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -224,10 +224,6 @@ type Reference struct { ScopeAST *d2ast.Map `json:"-"` } -func (r *Reference) Nulled() bool { - return r.MapKey != nil && len(r.MapKey.Edges) == 0 && r.MapKey.Value.Null != nil -} - func (r Reference) MapKeyEdgeDest() bool { return r.Key == r.MapKey.Edges[r.MapKeyEdgeIndex].Dst } @@ -1155,10 +1151,6 @@ type EdgeReference struct { ScopeAST *d2ast.Map `json:"-"` } -func (er *EdgeReference) Nulled() bool { - return er.MapKey != nil && er.MapKey.Value.Null != nil -} - func (e *Edge) GetAstEdge() *d2ast.Edge { return e.References[0].Edge } diff --git a/d2ir/compile.go b/d2ir/compile.go index 20a03b103e..f5d92d043d 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -150,6 +150,10 @@ func (c *compiler) compileKey(refctx *RefContext) { } func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext) { + if refctx.Key != nil && len(refctx.Key.Edges) == 0 && refctx.Key.Value.Null != nil { + dst.DeleteField(kp.IDA()...) + return + } f, err := dst.EnsureField(kp, refctx) if err != nil { c.err.Errors = append(c.err.Errors, err.(d2ast.Error)) @@ -353,6 +357,11 @@ func (c *compiler) compileEdges(refctx *RefContext) { eida := NewEdgeIDs(refctx.Key) for i, eid := range eida { + if refctx.Key != nil && refctx.Key.Value.Null != nil { + refctx.ScopeMap.DeleteEdge(eid) + continue + } + refctx = refctx.Copy() refctx.Edge = refctx.Key.Edges[i] diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 7234256f76..bb5ef5f8d5 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -738,6 +738,20 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext) (*Field, return f.Map().ensureField(i+1, kp, refctx) } +func (m *Map) DeleteEdge(eid *EdgeID) *Edge { + if eid == nil { + return nil + } + + for i, e := range m.Edges { + if e.ID.Match(eid) { + m.Edges = append(m.Edges[:i], m.Edges[i+1:]...) + return e + } + } + return nil +} + func (m *Map) DeleteField(ida ...string) *Field { if len(ida) == 0 { return nil @@ -751,6 +765,17 @@ func (m *Map) DeleteField(ida ...string) *Field { continue } if len(rest) == 0 { + for _, fr := range f.References { + for i, e := range m.Edges { + for _, er := range e.References { + if er.Context == fr.Context { + m.DeleteEdge(e.ID) + i-- + break + } + } + } + } m.Fields = append(m.Fields[:i], m.Fields[i+1:]...) return f } diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json index 9f83b57fc3..66e103bb67 100644 --- a/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json @@ -156,26 +156,6 @@ }, "key_path_index": 0, "map_key_edge_index": 0 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 } ], "attributes": { @@ -221,26 +201,6 @@ }, "key_path_index": 0, "map_key_edge_index": 0 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15", - "value": [ - { - "string": "b", - "raw_string": "b" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 } ], "attributes": { diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json index 758fbbabb3..7d93bdeea0 100644 --- a/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.exp.json @@ -232,37 +232,6 @@ }, "key_path_index": 0, "map_key_edge_index": -1 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:3:25", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:0:22-5:1:23", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - }, - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/delete-children.d2,5:2:24-5:3:25", - "value": [ - { - "string": "b", - "raw_string": "b" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": -1 } ], "attributes": { diff --git a/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json b/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json index b7d4840b6a..c0b0e4fc12 100644 --- a/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.exp.json @@ -137,40 +137,20 @@ ], "objects": [ { - "id": "y", - "id_val": "y", + "id": "x", + "id_val": "x", "references": [ { "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,1:0:1-1:1:2", - "value": [ - { - "string": "y", - "raw_string": "y" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": -1 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", "path": [ { "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", "value": [ { - "string": "y", - "raw_string": "y" + "string": "x", + "raw_string": "x" } ] } @@ -183,7 +163,7 @@ ], "attributes": { "label": { - "value": "" + "value": "x" }, "labelDimensions": { "width": 0, @@ -202,20 +182,20 @@ "zIndex": 0 }, { - "id": "x", - "id_val": "x", + "id": "y", + "id_val": "y", "references": [ { "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", "path": [ { "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:0:9-2:1:10", + "range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/no-delete-connection.d2,2:5:14-2:6:15", "value": [ { - "string": "x", - "raw_string": "x" + "string": "y", + "raw_string": "y" } ] } @@ -228,7 +208,7 @@ ], "attributes": { "label": { - "value": "x" + "value": "y" }, "labelDimensions": { "width": 0, diff --git a/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.exp.json b/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.exp.json new file mode 100644 index 0000000000..9a3a10c592 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.exp.json @@ -0,0 +1,226 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,0:0:0-8:0:42", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,1:0:1-1:1:2", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,3:0:4-7:1:41", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,3:0:4-3:9:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,3:0:4-3:9:13", + "value": [ + { + "string": "scenarios", + "raw_string": "scenarios" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,3:11:15-7:1:41", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,4:2:19-6:3:39", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,4:2:19-4:3:20", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,4:2:19-4:3:20", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,4:5:22-6:3:39", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,5:4:28-5:11:35", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,5:4:28-5:5:29", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,5:4:28-5:5:29", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,5:7:31-5:11:35" + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "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": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/multiboard/scenario.d2,1:0:1-1:1:2", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "scenarios": [ + { + "name": "a", + "isFolderOnly": false, + "ast": { + "range": ",1:0:0-2:0:0", + "nodes": null + }, + "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": null + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.exp.json new file mode 100644 index 0000000000..92f2e464a2 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.exp.json @@ -0,0 +1,184 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,0:0:0-4:0:32", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:0:1-1:20:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:0:1-1:15:16", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:2:3-1:7:8", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:8:9-1:15:16", + "value": [ + { + "string": "opacity", + "raw_string": "opacity" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,1:17:18-1:20:21", + "raw": "0.2", + "value": "1/5" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,2:0:22-2:7:29", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,2:0:22-2:1:23", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,2:0:22-2:1:23", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,2:3:25-2:7:29" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,3:0:30-3:1:31", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,3:0:30-3:1:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,3:0:30-3:1:31", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "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/nulls/reappear/attribute-reset.d2,3:0:30-3:1:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/attribute-reset.d2,3:0:30-3:1:31", + "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 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.exp.json new file mode 100644 index 0000000000..3e297fcecf --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.exp.json @@ -0,0 +1,309 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,0:0:0-4:0:21", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:0:1-1:5:6", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:0:1-1:5:6", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:2:3-1:3:4", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:4:5-1:5:6", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,2:0:7-2:9:16", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,2:0:7-2:3:10", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,2:0:7-2:1:8", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,2:2:9-2:3:10", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,2:5:12-2:9:16" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:3:20", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:3:20", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:1:18", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:2:19-3:3:20", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "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/nulls/reappear/children-reset.d2,1:0:1-1:5:6", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:2:3-1:3:4", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,1:4:5-1:5:6", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:3:20", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:1:18", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:2:19-3:3:20", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "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": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:3:20", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:0:17-3:1:18", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/children-reset.d2,3:2:19-3:3:20", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 1, + "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 +} diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.exp.json new file mode 100644 index 0000000000..d6e3860e18 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.exp.json @@ -0,0 +1,224 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,0:0:0-4:0:18", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,2:0:8-2:7:15", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,2:0:8-2:1:9", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,2:3:11-2:7:15" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,3:0:16-3:1:17", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,3:0:16-3:1:17", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,3:0:16-3:1:17", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "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": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "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/nulls/reappear/edge-reset.d2,3:0:16-3:1:17", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge-reset.d2,3:0:16-3:1:17", + "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 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json index 726082f0ec..f22a534680 100644 --- a/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/edge.exp.json @@ -179,7 +179,7 @@ }, "edges": [ { - "index": 1, + "index": 0, "isCurve": false, "src_arrow": false, "dst_arrow": true, @@ -234,26 +234,6 @@ "key_path_index": 0, "map_key_edge_index": 0 }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:1:9-2:2:10", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 - }, { "key": { "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:0:26-3:1:27", @@ -319,26 +299,6 @@ "key_path_index": 0, "map_key_edge_index": 0 }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,2:6:14-2:7:15", - "value": [ - { - "string": "b", - "raw_string": "b" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": 0 - }, { "key": { "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/edge.d2,3:5:31-3:6:32", diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/reset.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/reset.exp.json new file mode 100644 index 0000000000..cc75922091 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/reset.exp.json @@ -0,0 +1,184 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,0:0:0-4:0:32", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:0:1-1:20:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:0:1-1:15:16", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:2:3-1:7:8", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:8:9-1:15:16", + "value": [ + { + "string": "opacity", + "raw_string": "opacity" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,1:17:18-1:20:21", + "raw": "0.2", + "value": "1/5" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,2:0:22-2:7:29", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,2:0:22-2:1:23", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,2:0:22-2:1:23", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,2:3:25-2:7:29" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,3:0:30-3:1:31", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,3:0:30-3:1:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,3:0:30-3:1:31", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "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/nulls/reappear/reset.d2,3:0:30-3:1:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/reset.d2,3:0:30-3:1:31", + "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 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json index e8a97f7703..744b757f32 100644 --- a/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json +++ b/testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json @@ -109,46 +109,6 @@ "id": "a", "id_val": "a", "references": [ - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,1:0:1-1:1:2", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": -1 - }, - { - "key": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", - "path": [ - { - "unquoted_string": { - "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,2:0:3-2:1:4", - "value": [ - { - "string": "a", - "raw_string": "a" - } - ] - } - } - ] - }, - "key_path_index": 0, - "map_key_edge_index": -1 - }, { "key": { "range": "d2/testdata/d2compiler/TestCompile2/nulls/reappear/shape.d2,3:0:11-3:1:12", @@ -172,7 +132,7 @@ ], "attributes": { "label": { - "value": "" + "value": "a" }, "labelDimensions": { "width": 0, From c2b5cb9e56a600b3399ba03ff8999122c82e4c42 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 11:58:16 -0700 Subject: [PATCH 10/12] cleanup --- d2graph/d2graph.go | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 9feb43fdaf..eb47de274f 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -73,37 +73,6 @@ func (g *Graph) RootBoard() *Graph { return g } -// DeleteObject deletes an object along with all its descendants. -// It also deletes all edges connected to it or a descendant. -func (g *Graph) DeleteObject(obj *Object) { - for i, obj2 := range g.Objects { - if obj == obj2 { - g.Objects = append(g.Objects[:i], g.Objects[i+1:]...) - i-- - } - } - obj.Parent.removeChild(obj) - - for i, e := range g.Edges { - if e.Src == obj || e.Dst == obj { - g.Edges = append(g.Edges[:i], g.Edges[i+1:]...) - } - } - - for _, ch := range obj.ChildrenArray { - g.DeleteObject(ch) - } -} - -func (g *Graph) DeleteEdge(e *Edge) { - for i, e2 := range g.Edges { - if e == e2 { - g.Edges = append(g.Edges[:i], g.Edges[i+1:]...) - i-- - } - } -} - type LayoutGraph func(context.Context, *Graph) error // TODO consider having different Scalar types From 0749d4fb41d1341d5a0edfb74b0e79ab3b5de2d5 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Jun 2023 12:15:24 -0700 Subject: [PATCH 11/12] attribute --- d2compiler/compile_test.go | 20 +- d2ir/d2ir.go | 15 ++ .../nulls/basic/attribute.exp.json | 205 ++++++++++++++++++ 3 files changed, 230 insertions(+), 10 deletions(-) create mode 100644 testdata/d2compiler/TestCompile2/nulls/basic/attribute.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index db89c23199..a283166be4 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2956,16 +2956,16 @@ a -> b assert.Equal(t, 0, len(g.Edges)) }, }, - // { - // name: "attribute", - // run: func(t *testing.T) { - // g := assertCompile(t, ` - // a.style.opacity: 0.2 - // a.style.opacity: null - // `, "") - // assert.Equal(t, "0.2", g.Objects[0].Attributes.Style.Opacity.Value) - // }, - // }, + { + name: "attribute", + run: func(t *testing.T) { + g := assertCompile(t, ` +a.style.opacity: 0.2 +a.style.opacity: null + `, "") + assert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[0].Attributes.Style.Opacity) + }, + }, } for _, tc := range tca { diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index bb5ef5f8d5..dc239975a3 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -777,6 +777,21 @@ func (m *Map) DeleteField(ida ...string) *Field { } } m.Fields = append(m.Fields[:i], m.Fields[i+1:]...) + + // If a field was deleted from a keyword-holder keyword and that holder is empty, + // then that holder becomes meaningless and should be deleted too + parent := ParentField(f) + for keyword := range d2graph.ReservedKeywordHolders { + if parent != nil && parent.Name == keyword && len(parent.Map().Fields) == 0 { + styleParentMap := ParentMap(parent) + for i, f := range styleParentMap.Fields { + if f.Name == keyword { + styleParentMap.Fields = append(styleParentMap.Fields[:i], styleParentMap.Fields[i+1:]...) + break + } + } + } + } return f } if f.Map() != nil { diff --git a/testdata/d2compiler/TestCompile2/nulls/basic/attribute.exp.json b/testdata/d2compiler/TestCompile2/nulls/basic/attribute.exp.json new file mode 100644 index 0000000000..8b29a94976 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/nulls/basic/attribute.exp.json @@ -0,0 +1,205 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,0:0:0-3:3:47", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:0:1-1:20:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:0:1-1:15:16", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:2:3-1:7:8", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:8:9-1:15:16", + "value": [ + { + "string": "opacity", + "raw_string": "opacity" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:17:18-1:20:21", + "raw": "0.2", + "value": "1/5" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:0:22-2:21:43", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:0:22-2:15:37", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:0:22-2:1:23", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:2:24-2:7:29", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:8:30-2:15:37", + "value": [ + { + "string": "opacity", + "raw_string": "opacity" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "null": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,2:17:39-2:21:43" + } + } + } + } + ] + }, + "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/basic/attribute.d2,1:0:1-1:15:16", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:2:3-1:7:8", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/attribute.d2,1:8:9-1:15:16", + "value": [ + { + "string": "opacity", + "raw_string": "opacity" + } + ] + } + } + ] + }, + "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 + } + ] + }, + "err": null +} From 7973e4927d9d0f73be66fc19680e8268e856c41c Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 27 Jun 2023 13:36:33 -0700 Subject: [PATCH 12/12] change test expected behavior --- d2ir/compile_test.go | 6 +- .../d2ir/TestCompile/fields/null.exp.json | 129 +----------------- 2 files changed, 2 insertions(+), 133 deletions(-) diff --git a/d2ir/compile_test.go b/d2ir/compile_test.go index 516c42be4a..ab7173c8e0 100644 --- a/d2ir/compile_test.go +++ b/d2ir/compile_test.go @@ -190,11 +190,7 @@ func testCompileFields(t *testing.T) { m, err := compile(t, `pq: pq pq: null`) assert.Success(t, err) - assertQuery(t, m, 1, 0, nil, "") - // null doesn't delete pq from *Map so that for language tooling - // we maintain the references. - // Instead d2compiler will ensure it doesn't get rendered. - assertQuery(t, m, 0, 0, nil, "pq") + assertQuery(t, m, 0, 0, nil, "") }, }, } diff --git a/testdata/d2ir/TestCompile/fields/null.exp.json b/testdata/d2ir/TestCompile/fields/null.exp.json index 022cb550c4..e7db96e23b 100644 --- a/testdata/d2ir/TestCompile/fields/null.exp.json +++ b/testdata/d2ir/TestCompile/fields/null.exp.json @@ -1,131 +1,4 @@ { - "fields": [ - { - "name": "pq", - "primary": { - "value": { - "range": "TestCompile/fields/null.d2,1:4:11-1:8:15" - } - }, - "references": [ - { - "string": { - "range": "TestCompile/fields/null.d2,0:0:0-0:2:2", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - }, - "key_path": { - "range": "TestCompile/fields/null.d2,0:0:0-0:2:2", - "path": [ - { - "unquoted_string": { - "range": "TestCompile/fields/null.d2,0:0:0-0:2:2", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - } - } - ] - }, - "context": { - "edge": null, - "key": { - "range": "TestCompile/fields/null.d2,0:0:0-0:6:6", - "key": { - "range": "TestCompile/fields/null.d2,0:0:0-0:2:2", - "path": [ - { - "unquoted_string": { - "range": "TestCompile/fields/null.d2,0:0:0-0:2:2", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - } - } - ] - }, - "primary": {}, - "value": { - "unquoted_string": { - "range": "TestCompile/fields/null.d2,0:4:4-0:6:6", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - } - } - } - } - }, - { - "string": { - "range": "TestCompile/fields/null.d2,1:0:7-1:2:9", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - }, - "key_path": { - "range": "TestCompile/fields/null.d2,1:0:7-1:2:9", - "path": [ - { - "unquoted_string": { - "range": "TestCompile/fields/null.d2,1:0:7-1:2:9", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - } - } - ] - }, - "context": { - "edge": null, - "key": { - "range": "TestCompile/fields/null.d2,1:0:7-1:8:15", - "key": { - "range": "TestCompile/fields/null.d2,1:0:7-1:2:9", - "path": [ - { - "unquoted_string": { - "range": "TestCompile/fields/null.d2,1:0:7-1:2:9", - "value": [ - { - "string": "pq", - "raw_string": "pq" - } - ] - } - } - ] - }, - "primary": {}, - "value": { - "null": { - "range": "TestCompile/fields/null.d2,1:4:11-1:8:15" - } - } - } - } - } - ] - } - ], + "fields": [], "edges": null }