d2ir: fix edge glob edge case

This commit is contained in:
Alexander Wang 2024-08-05 17:34:41 -07:00
parent ddf68ca4a3
commit df0648a4d6
No known key found for this signature in database
GPG key ID: BE3937D0D52D8927
5 changed files with 3263 additions and 1530 deletions

View file

@ -10,3 +10,4 @@
- Sequence diagram multi-line edge labels no longer can collide with other elements [#2049](https://github.com/terrastruct/d2/pull/2049)
- Sequence diagram long self-referential edge labels no longer can collide neighboring actors (or its own) lifeline edges [#2050](https://github.com/terrastruct/d2/pull/2050)
- Globs: An edge case was fixed where globs used in edges were creating nodes when it shouldn't have [#2051](https://github.com/terrastruct/d2/pull/2051)

View file

@ -435,7 +435,7 @@ func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []string, _ error)
}
for len(eid.SrcPath) > 1 && len(eid.DstPath) > 1 {
if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) || eid.SrcPath[0] == "*" {
if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) || strings.Contains(eid.SrcPath[0], "*") {
return eid, m, common, nil
}
common = append(common, eid.SrcPath[0])
@ -1218,11 +1218,11 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c *
eid2.SrcPath = RelIDA(m, src)
eid2.DstPath = RelIDA(m, dst)
e, err := m.createEdge2(eid2, refctx, gctx, c, src, dst)
es, err := m.createEdge2(eid2, refctx, gctx, c, src, dst)
if err != nil {
return err
}
if e != nil {
for _, e := range es {
*ea = append(*ea, e)
}
}
@ -1230,7 +1230,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c *
return nil
}
func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c *compiler, src, dst *Field) (*Edge, error) {
func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c *compiler, src, dst *Field) ([]*Edge, error) {
if NodeBoardKind(src) != "" {
return nil, d2parser.Errorf(refctx.Edge.Src, "cannot create edges between boards")
}
@ -1241,6 +1241,45 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c
return nil, d2parser.Errorf(refctx.Edge, "cannot create edges between boards")
}
eid, m, common, err := eid.resolve(m)
if err != nil {
return nil, d2parser.Errorf(refctx.Edge, err.Error())
}
if len(common) > 0 {
commonKP := d2ast.MakeKeyPath(common)
lastMatch := 0
for i, el := range commonKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
realEl := refctx.Edge.Src.Path[j]
if el.ScalarString() == realEl.ScalarString() {
commonKP.Path[i] = realEl
lastMatch += j + 1
}
}
}
fa, err := m.EnsureField(commonKP, nil, true, c)
if err != nil {
return nil, err
}
var edges []*Edge
for _, f := range fa {
if _, ok := f.Composite.(*Array); ok {
return nil, d2parser.Errorf(refctx.Edge.Src, "cannot index into array")
}
if f.Map() == nil {
f.Composite = &Map{
parent: f,
}
}
edges2, err := f.Map().createEdge2(eid, refctx, gctx, c, src, dst)
if err != nil {
return nil, err
}
edges = append(edges, edges2...)
}
return edges, nil
}
eid.Index = nil
eid.Glob = true
ea := m.GetEdges(eid, nil, nil)
@ -1276,7 +1315,7 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c
m.Edges = append(m.Edges, e)
return e, nil
return []*Edge{e}, nil
}
func (s *Scalar) AST() d2ast.Node {

View file

@ -157,6 +157,24 @@ sh*.an* -> sh*.an*`)
assertQuery(t, m, 0, 0, nil, "shared.(animal -> animate)[0]")
},
},
{
name: "edge/4",
run: func(t testing.TB) {
m, err := compile(t, `app_a: {
x
}
app_b: {
y
}
app_*.x -> app_*.y`)
assert.Success(t, err)
assertQuery(t, m, 6, 4, nil, "")
assertQuery(t, m, 2, 1, nil, "app_a")
assertQuery(t, m, 2, 1, nil, "app_b")
},
},
{
name: "edge-glob-index",
run: func(t testing.TB) {

1722
testdata/d2ir/TestCompile/patterns/edge/4.exp.json generated vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff