From ba78c3bacc5ab67b8953f624be2abbc2f6862053 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 30 Apr 2025 09:08:58 -0600 Subject: [PATCH] d2oracle.UpdateImport: support directory updates --- d2oracle/edit.go | 41 +- d2oracle/edit_test.go | 55 +++ .../remove_directory_import.exp.json | 246 +++++++++++ .../update_deep_directory_paths.exp.json | 416 ++++++++++++++++++ .../update_directory_import.exp.json | 416 ++++++++++++++++++ 5 files changed, 1165 insertions(+), 9 deletions(-) create mode 100644 testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 18447fed9..06a8c0ac9 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -3365,7 +3365,8 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node := m.Nodes[i] if node.Import != nil { - if node.Import.PathWithPre() == oldPath { + importPath := node.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { if newPath == nil { if node.Import.Spread { m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) @@ -3374,7 +3375,7 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node.Import = nil } } else { - updateImportPath(node.Import, *newPath) + updateImportPath(node.Import, getNewImportPath(importPath, oldPath, *newPath)) } continue } @@ -3382,7 +3383,8 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri if node.MapKey != nil { if node.MapKey.Value.Import != nil { - if node.MapKey.Value.Import.PathWithPre() == oldPath { + importPath := node.MapKey.Value.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { if newPath == nil { if node.MapKey.Value.Import.Spread && node.MapKey.Value.Map == nil { m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) @@ -3391,7 +3393,7 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node.MapKey.Value.Import = nil } } else { - updateImportPath(node.MapKey.Value.Import, *newPath) + updateImportPath(node.MapKey.Value.Import, getNewImportPath(importPath, oldPath, *newPath)) } } } @@ -3401,11 +3403,14 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri value, ok := primaryImport.(d2ast.Value) if ok { importBox := d2ast.MakeValueBox(value) - if importBox.Import != nil && importBox.Import.PathWithPre() == oldPath { - if newPath == nil { - node.MapKey.Primary = d2ast.ScalarBox{} - } else { - updateImportPath(importBox.Import, *newPath) + if importBox.Import != nil { + importPath := importBox.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { + if newPath == nil { + node.MapKey.Primary = d2ast.ScalarBox{} + } else { + updateImportPath(importBox.Import, getNewImportPath(importPath, oldPath, *newPath)) + } } } } @@ -3427,3 +3432,21 @@ func updateImportPath(imp *d2ast.Import, newPath string) { } } } + +func matchesImportPath(importPath, oldPath string) bool { + isDir := strings.HasSuffix(oldPath, "/") + if isDir { + return strings.HasPrefix(importPath, oldPath) + } + return importPath == oldPath +} + +func getNewImportPath(importPath, oldPath, newPath string) string { + isOldDir := strings.HasSuffix(oldPath, "/") + isNewDir := strings.HasSuffix(newPath, "/") + if isOldDir && isNewDir { + relPath := importPath[len(oldPath):] + return newPath + relPath + } + return newPath +} diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index d17c3919e..7a022f355 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9824,6 +9824,61 @@ layers: { ...@woof } } +`, + }, + { + name: "update_directory_import", + text: `x: @foo/bar +y: @foo/baz +z +`, + fsTexts: map[string]string{ + "foo/bar.d2": "k", + "foo/baz.d2": "k", + "woof/bar.d2": "k", + "woof/baz.d2": "k", + }, + path: "foo/", + newPath: go2.Pointer("woof/"), + exp: `x: @woof/bar +y: @woof/baz +z +`, + }, + { + name: "remove_directory_import", + text: `x: @foo/bar +y: @foo/baz +z +`, + fsTexts: map[string]string{ + "foo/bar.d2": "k", + "foo/baz.d2": "k", + }, + path: "foo/", + newPath: nil, + exp: `x +y +z +`, + }, + { + name: "update_deep_directory_paths", + text: `x: @foo/bar/baz +y: @foo/qux/quux +z +`, + fsTexts: map[string]string{ + "foo/bar/baz.d2": "k", + "foo/qux/quux.d2": "k", + "woof/bar/baz.d2": "k", + "woof/qux/quux.d2": "k", + }, + path: "foo/", + newPath: go2.Pointer("woof/"), + exp: `x: @woof/bar/baz +y: @woof/qux/quux +z `, }, } diff --git a/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json b/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json new file mode 100644 index 000000000..2183e42b6 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json @@ -0,0 +1,246 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:6", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,1:0:2-1:1:3", + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:0:4-2:1:5", + "key": { + "range": "index.d2,2:0:4-2:1:5", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:4-2:1:5", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "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": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:4-2:1:5", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:4-2:1:5", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json b/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json new file mode 100644 index 000000000..629973701 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json @@ -0,0 +1,416 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:37", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:16:16", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:16:16", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:16:16", + "value": [ + { + "string": "woof/bar/baz", + "raw_string": "woof/bar/baz" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:17-1:17:34", + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:3:20-1:17:34", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:21-1:17:34", + "value": [ + { + "string": "woof/qux/quux", + "raw_string": "woof/qux/quux" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:0:35-2:1:36", + "key": { + "range": "index.d2,2:0:35-2:1:36", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:35-2:1:36", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "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": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/bar/baz.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/bar/baz.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/qux/quux.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/qux/quux.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:35-2:1:36", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:35-2:1:36", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json b/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json new file mode 100644 index 000000000..26b681263 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json @@ -0,0 +1,416 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:28", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:12:12", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:12:12", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:12:12", + "value": [ + { + "string": "woof/bar", + "raw_string": "woof/bar" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:13-1:12:25", + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:3:16-1:12:25", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:17-1:12:25", + "value": [ + { + "string": "woof/baz", + "raw_string": "woof/baz" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:0:26-2:1:27", + "key": { + "range": "index.d2,2:0:26-2:1:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:26-2:1:27", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "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": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/bar.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/bar.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/baz.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/baz.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:26-2:1:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:26-2:1:27", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +}