Skip to content

Commit

Permalink
d2ir: enable linking beyond board root
Browse files Browse the repository at this point in the history
  • Loading branch information
alixander committed Aug 26, 2024
1 parent 9cc7a04 commit 1a7d5b3
Show file tree
Hide file tree
Showing 9 changed files with 2,974 additions and 8 deletions.
2 changes: 2 additions & 0 deletions ci/release/changelogs/next.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#### Features 🚀

- Vars: Variable definitions can now refer to other variables in the current scope [#2052](https://github.com/terrastruct/d2/pull/2052)
- Composition: Imported boards can use underscores to reference boards beyond its own
scope (e.g. to a sibling board at the scope its imported to) [#2075](https://github.com/terrastruct/d2/pull/2075)

#### Improvements 🧹

Expand Down
76 changes: 75 additions & 1 deletion d2compiler/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,7 @@ layers: {
}
}
}`,
expErr: `d2/testdata/d2compiler/TestCompile/link-board-underscore-not-found.d2:7:9: invalid underscore usage`,
expErr: `d2/testdata/d2compiler/TestCompile/link-board-underscore-not-found.d2:7:9: linked board not found`,
},
{
name: "border-radius-negative",
Expand Down Expand Up @@ -3114,6 +3114,80 @@ layers: {
"y/n.d2": "p",
},
},
{
name: "import-link-layer-1",
text: `k
layers: {
x: {...@y}
z: { hi }
}`,
files: map[string]string{
"y.d2": `a.link: _.layers.z
`,
},
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "root.layers.z", g.Layers[0].Objects[0].Link.Value)
},
},
{
name: "import-link-layer-2",
text: `...@y
layers: {
z: { hi }
}`,
files: map[string]string{
"y.d2": `a.link: layers.z
`,
},
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "root.layers.z", g.Objects[0].Link.Value)
},
},
{
name: "import-link-layer-3",
text: `k
layers: {
x: {...@y}
z: { hi }
}`,
files: map[string]string{
"y.d2": `a
layers: {
lol: {
asdf.link: _._.layers.z
}
}
`,
},
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "root.layers.z", g.Layers[0].Layers[0].Objects[0].Link.Value)
},
},
{
name: "import-link-layer-4",
text: `k
layers: {
x: @y
z: { hi }
}`,
files: map[string]string{
"y.d2": `a
layers: {
lol: {
asdf.link: _.layers.z
}
z: { fjf }
}
`,
},
assertions: func(t *testing.T, g *d2graph.Graph) {
tassert.Equal(t, "root.layers.x.layers.z", g.Layers[0].Layers[0].Objects[0].Link.Value)
},
},
{
name: "sql-table-header-newline",
text: `x: {
Expand Down
18 changes: 13 additions & 5 deletions d2ir/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,16 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) {
continue
}

extendedIDA := append(importIDA, linkIDA[1:]...)
for _, id := range linkIDA[1:] {
if id == "_" {
linkIDA = append([]string{linkIDA[0]}, linkIDA[2:]...)
importIDA = importIDA[:len(importIDA)-2]
} else {
break
}
}

extendedIDA := append(importIDA[:len(importIDA)], linkIDA[1:]...)
kp := d2ast.MakeKeyPath(extendedIDA)
s := d2format.Format(kp)
f.Primary_.Value = d2ast.MakeValueBox(d2ast.FlatUnquotedString(s)).ScalarBox().Unbox()
Expand Down Expand Up @@ -984,10 +993,9 @@ func (c *compiler) compileLink(f *Field, refctx *RefContext) {
// Resolve underscores
for len(linkIDA) > 0 && linkIDA[0] == "_" {
if len(scopeIDA) < 2 {
// IR compiler only validates bad underscore usage
// The compiler will validate if the target board actually exists
c.errorf(refctx.Key.Key, "invalid underscore usage")
return
// Leave the underscore. It will fail in compiler as a standalone board,
// but if imported, will get further resolved in extendLinks
break
}
// pop 2 off path per one underscore
scopeIDA = scopeIDA[:len(scopeIDA)-2]
Expand Down
Loading

0 comments on commit 1a7d5b3

Please sign in to comment.