Skip to content

Commit

Permalink
d2ir: Fix filters on nested fields
Browse files Browse the repository at this point in the history
See test on edges
  • Loading branch information
nhooyr committed Jul 30, 2023
1 parent 6358a44 commit d0d3ebe
Show file tree
Hide file tree
Showing 5 changed files with 3,518 additions and 9 deletions.
19 changes: 19 additions & 0 deletions d2ast/d2ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,19 @@ func (mk *Key) SetScalar(scalar ScalarBox) {
}
}

func (mk *Key) HasQueryGlob() bool {
if mk.Key.HasGlob() && len(mk.Edges) == 0 {
return true
}
if mk.EdgeIndex != nil && mk.EdgeIndex.Glob && mk.EdgeKey == nil {
return true
}
if mk.EdgeKey.HasGlob() {
return true
}
return false
}

type KeyPath struct {
Range Range `json:"range"`
Path []*StringBox `json:"path"`
Expand Down Expand Up @@ -748,6 +761,9 @@ func (kp *KeyPath) Copy() *KeyPath {
}

func (kp *KeyPath) HasDoubleGlob() bool {
if kp == nil {
return false
}
for _, el := range kp.Path {
if el.UnquotedString != nil && el.ScalarString() == "**" {
return true
Expand All @@ -757,6 +773,9 @@ func (kp *KeyPath) HasDoubleGlob() bool {
}

func (kp *KeyPath) HasGlob() bool {
if kp == nil {
return false
}
for _, el := range kp.Path {
if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
return true
Expand Down
22 changes: 14 additions & 8 deletions d2ir/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type compiler struct {
// importCache enables reuse of files imported multiple times.
importCache map[string]*Map
utf16 bool

globStack []bool
}

type CompileOptions struct {
Expand Down Expand Up @@ -429,6 +431,10 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool {
if !refctx.Key.Ampersand {
return true
}
if len(c.globStack) == 0 || !c.globStack[len(c.globStack)-1] {
c.errorf(refctx.Key, "glob filters cannot be used outside globs")
return false
}
if len(refctx.Key.Edges) > 0 {
return true
}
Expand All @@ -451,16 +457,12 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool {
}

func (c *compiler) _ampersandFilter(f *Field, refctx *RefContext) bool {
f2 := ParentMap(f).Map().GetField(refctx.Key.Key.IDA()...)
if f2 == nil {
return false
}
if refctx.Key.Value.ScalarBox().Unbox() == nil {
c.errorf(refctx.Key, "ampersand filters cannot be composites")
c.errorf(refctx.Key, "glob filters cannot be composites")
return false
}

if a, ok := f2.Composite.(*Array); ok {
if a, ok := f.Composite.(*Array); ok {
for _, v := range a.Values {
if s, ok := v.(*Scalar); ok {
if refctx.Key.Value.ScalarBox().Unbox().ScalarString() == s.Value.ScalarString() {
Expand All @@ -470,11 +472,11 @@ func (c *compiler) _ampersandFilter(f *Field, refctx *RefContext) bool {
}
}

if f2.Primary_ == nil {
if f.Primary_ == nil {
return false
}

if refctx.Key.Value.ScalarBox().Unbox().ScalarString() != f2.Primary_.Value.ScalarString() {
if refctx.Key.Value.ScalarBox().Unbox().ScalarString() != f.Primary_.Value.ScalarString() {
return false
}

Expand Down Expand Up @@ -530,7 +532,9 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
// If new board type, use that as the new scope AST, otherwise, carry on
scopeAST = refctx.ScopeAST
}
c.globStack = append(c.globStack, refctx.Key.HasQueryGlob())
c.compileMap(f.Map(), refctx.Key.Value.Map, scopeAST)
c.globStack = c.globStack[:len(c.globStack)-1]
switch NodeBoardKind(f) {
case BoardScenario, BoardStep:
c.overlayClasses(f.Map())
Expand Down Expand Up @@ -767,7 +771,9 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
parent: e,
}
}
c.globStack = append(c.globStack, refctx.Key.HasQueryGlob())
c.compileMap(e.Map_, refctx.Key.Value.Map, refctx.ScopeAST)
c.globStack = c.globStack[:len(c.globStack)-1]
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
e.Primary_ = &Scalar{
parent: e,
Expand Down
40 changes: 39 additions & 1 deletion d2ir/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ catapult: {
assertQuery(t, m, 3, 0, nil, "catapult")
},
},
{
name: "edge",
run: func(t testing.TB) {
m, err := compile(t, `x -> y: {
source-arrowhead.shape: diamond
target-arrowhead.shape: diamond
}
x -> y
(x -> *)[*]: {
&source-arrowhead.shape: diamond
&target-arrowhead.shape: diamond
label: diamond shape arrowheads
}
`)
assert.Success(t, err)
assertQuery(t, m, 7, 2, nil, "")
assertQuery(t, m, 5, 0, nil, "(x -> y)[0]")
assertQuery(t, m, 0, 0, "diamond shape arrowheads", "(x -> y)[0].label")
assertQuery(t, m, 0, 0, nil, "(x -> y)[1]")
},
},
}

runa(t, tca)
Expand All @@ -97,6 +119,22 @@ catapult: {
TestCompile/filters/errors/bad-syntax.d2:9:1: unexpected map termination character } in file map`)
},
},
{
name: "no-glob",
run: func(t testing.TB) {
_, err := compile(t, `jacob.style: {
fill: red
multiple: true
}
jasmine.style: {
&fill: red
multiple: false
}
`)
assert.ErrorString(t, err, `TestCompile/filters/errors/no-glob.d2:7:3: glob filters cannot be used outside globs`)
},
},
{
name: "composite",
run: func(t testing.TB) {
Expand All @@ -111,7 +149,7 @@ TestCompile/filters/errors/bad-syntax.d2:9:1: unexpected map termination charact
}
}
`)
assert.ErrorString(t, err, `TestCompile/filters/errors/composite.d2:6:2: ampersand filters cannot be composites`)
assert.ErrorString(t, err, `TestCompile/filters/errors/composite.d2:6:2: glob filters cannot be composites`)
},
},
}
Expand Down
Loading

0 comments on commit d0d3ebe

Please sign in to comment.