From c12a4f6db0f42247d378ce0a66a7da2f759294e8 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 20 Jan 2025 18:55:23 -0800 Subject: [PATCH] implement connected filter --- d2compiler/compile_test.go | 19 + d2ir/compile.go | 16 + .../globs/connected-filter.exp.json | 386 ++++++++++++++++++ 3 files changed, 421 insertions(+) create mode 100644 testdata/d2compiler/TestCompile2/globs/connected-filter.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 640c949b4..a9b1c8c1e 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -5206,6 +5206,25 @@ y.link: https://google.com style.fill: red } a.b.c +`, ``) + assert.Equal(t, "a", g.Objects[0].ID) + assert.Equal(t, "red", g.Objects[0].Attributes.Style.Fill.Value) + assert.Equal(t, "b", g.Objects[1].ID) + assert.Equal(t, "red", g.Objects[1].Attributes.Style.Fill.Value) + assert.Equal(t, "c", g.Objects[2].ID) + assert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[2].Attributes.Style.Fill) + }, + }, + { + name: "connected-filter", + run: func(t *testing.T) { + g, _ := assertCompile(t, ` +*: { + &connected: true + style.fill: red +} +a -> b +c `, ``) assert.Equal(t, "a", g.Objects[0].ID) assert.Equal(t, "red", g.Objects[0].Attributes.Style.Fill.Value) diff --git a/d2ir/compile.go b/d2ir/compile.go index 57acd3bb2..156f7a41c 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -761,6 +761,22 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool { f := refctx.ScopeMap.Parent().(*Field) isLeaf := f.Map() == nil || !f.Map().IsContainer() return isLeaf == boolVal + case "connected": + raw := refctx.Key.Value.ScalarBox().Unbox().ScalarString() + boolVal, err := strconv.ParseBool(raw) + if err != nil { + c.errorf(refctx.Key, `&connected must be "true" or "false", got %q`, raw) + return false + } + f := refctx.ScopeMap.Parent().(*Field) + isConnected := false + for _, r := range f.References { + if r.InEdge() { + isConnected = true + break + } + } + return isConnected == boolVal case "label": f := &Field{} n := refctx.ScopeMap.Parent() diff --git a/testdata/d2compiler/TestCompile2/globs/connected-filter.exp.json b/testdata/d2compiler/TestCompile2/globs/connected-filter.exp.json new file mode 100644 index 000000000..72b949980 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/connected-filter.exp.json @@ -0,0 +1,386 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,0:0:0-7:0:54", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,1:0:1-4:1:44", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,1:0:1-1:1:2", + "value": [ + { + "string": "*", + "raw_string": "*" + } + ], + "pattern": [ + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,1:3:4-4:1:44", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,2:2:8-2:18:24", + "ampersand": true, + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,2:3:9-2:12:18", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,2:3:9-2:12:18", + "value": [ + { + "string": "connected", + "raw_string": "connected" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "boolean": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,2:14:20-2:18:24", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,3:2:27-3:17:42", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,3:2:27-3:12:37", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,3:2:27-3:7:32", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,3:8:33-3:12:37", + "value": [ + { + "string": "fill", + "raw_string": "fill" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,3:14:39-3:17:42", + "value": [ + { + "string": "red", + "raw_string": "red" + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:0:45-5:6:51", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:0:45-5:6:51", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:0:45-5:1:46", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:5:50-5:6:51", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:5:50-5:6:51", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,6:0:52-6:1:53", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,6:0:52-6:1:53", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,6:0:52-6:1:53", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": [ + { + "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/globs/connected-filter.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:0:45-5:1:46", + "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": { + "fill": { + "value": "red" + } + }, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:5:50-5:6:51", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,5:5:50-5:6:51", + "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": { + "fill": { + "value": "red" + } + }, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,6:0:52-6:1:53", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/connected-filter.d2,6:0:52-6:1:53", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}