From 0eb465bdc5240814a9a6b0b2d6161a2c70bd2e89 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 24 Sep 2024 21:17:05 -0600 Subject: [PATCH] d2compile: fix ordering substitutions --- d2compiler/compile.go | 1 + d2compiler/compile_test.go | 21 + d2graph/d2graph.go | 6 + .../TestCompile/spread_var_order.exp.json | 367 ++++++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 testdata/d2compiler/TestCompile/spread_var_order.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index b623d14a6..7f31e583d 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -378,6 +378,7 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { Scope: fr.Context_.Scope, ScopeAST: fr.Context_.ScopeAST, ScopeObj: parent, + IsVar: d2ir.IsVar(fr.Context_.ScopeMap), } if fr.Context_.ScopeMap != nil && !d2ir.IsVar(fr.Context_.ScopeMap) { scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context_.ScopeMap)) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index d2ed43f19..9f07ccd84 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2863,6 +2863,27 @@ c: ${Cherry} sf: ${SummerFruit} `, }, + { + name: "spread_var_order", + text: `vars: { + before_elem: { + "before_elem" + } + after_elem: { + "after_elem" + } +} + +...${before_elem} +elem +...${after_elem} +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, "before_elem", g.Objects[0].AbsID()) + tassert.Equal(t, "elem", g.Objects[1].AbsID()) + tassert.Equal(t, "after_elem", g.Objects[2].AbsID()) + }, + }, { name: "class-shape-class", text: `classes: { diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index d3c717644..ba6053a89 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -197,6 +197,7 @@ type Reference struct { Scope *d2ast.Map `json:"-"` ScopeObj *Object `json:"-"` ScopeAST *d2ast.Map `json:"-"` + IsVar bool `json:"-"` } func (r Reference) MapKeyEdgeDest() bool { @@ -1702,6 +1703,11 @@ func (g *Graph) SortObjectsByAST() { } r1 := o1.References[0] r2 := o2.References[0] + // If they are variable substitutions, leave them alone, as their + // references reflect where the variable is, not where the substitution is + if r1.IsVar || r2.IsVar { + return i < j + } return r1.Key.Path[r1.KeyPathIndex].Unbox().GetRange().Before(r2.Key.Path[r2.KeyPathIndex].Unbox().GetRange()) }) g.Objects = objects diff --git a/testdata/d2compiler/TestCompile/spread_var_order.exp.json b/testdata/d2compiler/TestCompile/spread_var_order.exp.json new file mode 100644 index 000000000..c71ac28d6 --- /dev/null +++ b/testdata/d2compiler/TestCompile/spread_var_order.exp.json @@ -0,0 +1,367 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,0:0:0-12:0:127", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,0:0:0-7:1:85", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,0:0:0-0:4:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,0:0:0-0:4:4", + "value": [ + { + "string": "vars", + "raw_string": "vars" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,0:6:6-7:1:85", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,1:2:10-3:3:46", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,1:2:10-1:13:21", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,1:2:10-1:13:21", + "value": [ + { + "string": "before_elem", + "raw_string": "before_elem" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,1:15:23-3:3:46", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,2:4:29-2:17:42", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,2:4:29-2:17:42", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,2:4:29-2:17:42", + "value": [ + { + "string": "before_elem", + "raw_string": "before_elem" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,4:2:49-6:3:83", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,4:2:49-4:12:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,4:2:49-4:12:59", + "value": [ + { + "string": "after_elem", + "raw_string": "after_elem" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,4:14:61-6:3:83", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,5:4:67-5:16:79", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,5:4:67-5:16:79", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,5:4:67-5:16:79", + "value": [ + { + "string": "after_elem", + "raw_string": "after_elem" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + } + } + } + }, + { + "substitution": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,9:0:87-9:17:104", + "spread": true, + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,9:5:92-9:16:103", + "value": [ + { + "string": "before_elem", + "raw_string": "before_elem" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,10:0:105-10:4:109", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,10:0:105-10:4:109", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,10:0:105-10:4:109", + "value": [ + { + "string": "elem", + "raw_string": "elem" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "substitution": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,11:0:110-11:16:126", + "spread": true, + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,11:5:115-11:15:125", + "value": [ + { + "string": "after_elem", + "raw_string": "after_elem" + } + ] + } + } + ] + } + } + ] + }, + "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": "before_elem", + "id_val": "before_elem", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,2:4:29-2:17:42", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,2:4:29-2:17:42", + "value": [ + { + "string": "before_elem", + "raw_string": "before_elem" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "before_elem" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "elem", + "id_val": "elem", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,10:0:105-10:4:109", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,10:0:105-10:4:109", + "value": [ + { + "string": "elem", + "raw_string": "elem" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "elem" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "after_elem", + "id_val": "after_elem", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,5:4:67-5:16:79", + "path": [ + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/spread_var_order.d2,5:4:67-5:16:79", + "value": [ + { + "string": "after_elem", + "raw_string": "after_elem" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "after_elem" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}