diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 076e5d6ea6..71fa327ddf 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -383,7 +383,7 @@ func _set(g *d2graph.Graph, baseAST *d2ast.Map, key string, tag, value *string) break } obj = o - imported = IsImported(baseAST, obj) + imported = IsImportedObj(baseAST, obj) var maybeNewScope *d2ast.Map if baseAST != g.AST || imported { @@ -481,8 +481,9 @@ func _set(g *d2graph.Graph, baseAST *d2ast.Map, key string, tag, value *string) if !ok { return errors.New("edge not found") } + imported = IsImportedEdge(baseAST, edge) refs := edge.References - if baseAST != g.AST { + if baseAST != g.AST || imported { refs = getWriteableEdgeRefs(edge, baseAST) } onlyInChain := true @@ -868,45 +869,52 @@ func Delete(g *d2graph.Graph, boardPath []string, key string) (_ *d2graph.Graph, return g, nil } - refs := e.References - if len(boardPath) > 0 { - refs := getWriteableEdgeRefs(e, baseAST) - if len(refs) != len(e.References) { - mk.Value = d2ast.MakeValueBox(&d2ast.Null{}) - } - } + imported := IsImportedEdge(baseAST, e) - if _, ok := mk.Value.Unbox().(*d2ast.Null); !ok { - ref := refs[0] - var refEdges []*d2ast.Edge - for _, ref := range refs { - refEdges = append(refEdges, ref.Edge) + if imported { + mk.Value = d2ast.MakeValueBox(&d2ast.Null{}) + appendMapKey(baseAST, mk) + } else { + refs := e.References + if len(boardPath) > 0 { + refs := getWriteableEdgeRefs(e, baseAST) + if len(refs) != len(e.References) { + mk.Value = d2ast.MakeValueBox(&d2ast.Null{}) + } } - ensureNode(g, refEdges, ref.ScopeObj, ref.Scope, ref.MapKey, ref.MapKey.Edges[ref.MapKeyEdgeIndex].Src, true) - ensureNode(g, refEdges, ref.ScopeObj, ref.Scope, ref.MapKey, ref.MapKey.Edges[ref.MapKeyEdgeIndex].Dst, false) - for i := len(e.References) - 1; i >= 0; i-- { - ref := e.References[i] - deleteEdge(g, ref.Scope, ref.MapKey, ref.MapKeyEdgeIndex) - } + if _, ok := mk.Value.Unbox().(*d2ast.Null); !ok { + ref := refs[0] + var refEdges []*d2ast.Edge + for _, ref := range refs { + refEdges = append(refEdges, ref.Edge) + } + ensureNode(g, refEdges, ref.ScopeObj, ref.Scope, ref.MapKey, ref.MapKey.Edges[ref.MapKeyEdgeIndex].Src, true) + ensureNode(g, refEdges, ref.ScopeObj, ref.Scope, ref.MapKey, ref.MapKey.Edges[ref.MapKeyEdgeIndex].Dst, false) - edges, ok := obj.FindEdges(mk) - if ok { - for _, e2 := range edges { - if e2.Index <= e.Index { - continue - } - for i := len(e2.References) - 1; i >= 0; i-- { - ref := e2.References[i] - if ref.MapKey.EdgeIndex != nil { - *ref.MapKey.EdgeIndex.Int-- + for i := len(e.References) - 1; i >= 0; i-- { + ref := e.References[i] + deleteEdge(g, ref.Scope, ref.MapKey, ref.MapKeyEdgeIndex) + } + + edges, ok := obj.FindEdges(mk) + if ok { + for _, e2 := range edges { + if e2.Index <= e.Index { + continue + } + for i := len(e2.References) - 1; i >= 0; i-- { + ref := e2.References[i] + if ref.MapKey.EdgeIndex != nil { + *ref.MapKey.EdgeIndex.Int-- + } } } } + } else { + // NOTE: it only needs to be after the last ref, but perhaps simplest and cleanest to append all nulls at the end + appendMapKey(baseAST, mk) } - } else { - // NOTE: it only needs to be after the last ref, but perhaps simplest and cleanest to append all nulls at the end - appendMapKey(baseAST, mk) } if len(boardPath) > 0 { replaced := ReplaceBoardNode(g.AST, baseAST, boardPath) @@ -925,10 +933,9 @@ func Delete(g *d2graph.Graph, boardPath []string, key string) (_ *d2graph.Graph, return g, nil } - imported := IsImported(baseAST, obj) + imported := IsImportedObj(baseAST, obj) if imported { - println(d2format.Format(boardG.AST)) mk.Value = d2ast.MakeValueBox(&d2ast.Null{}) appendMapKey(baseAST, mk) } else { diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 198cc83dc3..ab0737e382 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -2171,6 +2171,20 @@ layers: { b.style.fill: red } } +`, + }, + { + name: "import/9", + + text: `...@yo +`, + fsTexts: map[string]string{ + "yo.d2": `a -> b`, + }, + key: `(a -> b)[0].style.stroke`, + value: go2.Pointer(`red`), + exp: `...@yo +(a -> b)[0].style.stroke: red `, }, } @@ -7205,6 +7219,20 @@ scenarios: { x: null } } +`, + }, + { + name: "import/3", + + text: `...@meow +`, + fsTexts: map[string]string{ + "meow.d2": `a -> b +`, + }, + key: `(a -> b)[0]`, + exp: `...@meow +(a -> b)[0]: null `, }, } diff --git a/d2oracle/get.go b/d2oracle/get.go index 6e5721ee89..c33a465973 100644 --- a/d2oracle/get.go +++ b/d2oracle/get.go @@ -140,7 +140,7 @@ func GetParentID(g *d2graph.Graph, boardPath []string, absID string) (string, er return obj.Parent.AbsID(), nil } -func IsImported(ast *d2ast.Map, obj *d2graph.Object) bool { +func IsImportedObj(ast *d2ast.Map, obj *d2graph.Object) bool { for _, ref := range obj.References { if ref.Key.Range.Path != ast.Range.Path { return true @@ -150,6 +150,16 @@ func IsImported(ast *d2ast.Map, obj *d2graph.Object) bool { return false } +func IsImportedEdge(ast *d2ast.Map, edge *d2graph.Edge) bool { + for _, ref := range edge.References { + if ref.Edge.Range.Path != ast.Range.Path { + return true + } + } + + return false +} + func GetObj(g *d2graph.Graph, boardPath []string, absID string) *d2graph.Object { g = GetBoardGraph(g, boardPath) if g == nil { diff --git a/testdata/d2oracle/TestDelete/import/3.exp.json b/testdata/d2oracle/TestDelete/import/3.exp.json new file mode 100644 index 0000000000..90559179d1 --- /dev/null +++ b/testdata/d2oracle/TestDelete/import/3.exp.json @@ -0,0 +1,203 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:27", + "nodes": [ + { + "import": { + "range": "index.d2,0:0:0-0:8:8", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:8:8", + "value": [ + { + "string": "meow", + "raw_string": "meow" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "index.d2,1:0:9-1:17:26", + "edges": [ + { + "range": "index.d2,1:1:10-1:7:16", + "src": { + "range": "index.d2,1:1:10-1:2:11", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:1:10-1:2:11", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "index.d2,1:6:15-1:7:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:6:15-1:7:16", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "index.d2,1:8:17-1:11:20", + "int": 0, + "glob": false + }, + "primary": {}, + "value": { + "null": { + "range": "index.d2,1:13:22-1:17:26" + } + } + } + } + ] + }, + "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": "meow.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "meow.d2,0:0:0-0:1:1", + "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": "meow.d2,0:5:5-0:6:6", + "path": [ + { + "unquoted_string": { + "range": "meow.d2,0:5:5-0:6:6", + "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": "" +} diff --git a/testdata/d2oracle/TestSet/import/9.exp.json b/testdata/d2oracle/TestSet/import/9.exp.json new file mode 100644 index 0000000000..3c942e675f --- /dev/null +++ b/testdata/d2oracle/TestSet/import/9.exp.json @@ -0,0 +1,314 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:37", + "nodes": [ + { + "import": { + "range": "index.d2,0:0:0-0:6:6", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:6:6", + "value": [ + { + "string": "yo", + "raw_string": "yo" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "index.d2,1:0:7-1:29:36", + "edges": [ + { + "range": "index.d2,1:1:8-1:7:14", + "src": { + "range": "index.d2,1:1:8-1:2:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:1:8-1:2:9", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "index.d2,1:6:13-1:7:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:6:13-1:7:14", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "index.d2,1:8:15-1:11:18", + "int": 0, + "glob": false + }, + "edge_key": { + "range": "index.d2,1:12:19-1:24:31", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:12:19-1:17:24", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "index.d2,1:18:25-1:24:31", + "value": [ + { + "string": "stroke", + "raw_string": "stroke" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "index.d2,1:26:33-1:29:36", + "value": [ + { + "string": "red", + "raw_string": "red" + } + ] + } + } + } + } + ] + }, + "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 + }, + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "stroke": { + "value": "red" + } + }, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "yo.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "yo.d2,0:0:0-0:1:1", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "index.d2,1:1:8-1:2:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:1:8-1:2:9", + "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": "yo.d2,0:5:5-0:6:6", + "path": [ + { + "unquoted_string": { + "range": "yo.d2,0:5:5-0:6:6", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "index.d2,1:6:13-1:7:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:6:13-1:7:14", + "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": "" +}