d2ir: Fix filters on nested fields

See test on edges
This commit is contained in:
Anmol Sethi 2023-07-30 13:16:56 -07:00
parent 6358a44fcb
commit d0d3ebe17e
No known key found for this signature in database
GPG key ID: 8CEF1878FF10ADEB
5 changed files with 3518 additions and 9 deletions

View file

@ -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"`
@ -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
@ -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

View file

@ -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 {
@ -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
}
@ -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() {
@ -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
}
@ -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())
@ -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,

View file

@ -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)
@ -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) {
@ -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`)
},
},
}

2696
testdata/d2ir/TestCompile/filters/edge.exp.json generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,750 @@
{
"fields": [
{
"name": "jacob",
"composite": {
"fields": [
{
"name": "style",
"composite": {
"fields": [
{
"name": "fill",
"primary": {
"value": {
"range": "TestCompile/filters/errors/no-glob.d2,1:7:22-1:10:25",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:10:25",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:7:22-1:10:25",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
}
}
}
}
]
},
{
"name": "multiple",
"primary": {
"value": {
"range": "TestCompile/filters/errors/no-glob.d2,2:11:37-2:15:41",
"value": true
}
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:15:41",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"primary": {},
"value": {
"boolean": {
"range": "TestCompile/filters/errors/no-glob.d2,2:11:37-2:15:41",
"value": true
}
}
}
}
}
]
}
],
"edges": null
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:6:6-0:11:11",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:11:11",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:5:5",
"value": [
{
"string": "jacob",
"raw_string": "jacob"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:6:6-0:11:11",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-3:1:43",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:11:11",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:5:5",
"value": [
{
"string": "jacob",
"raw_string": "jacob"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:6:6-0:11:11",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "TestCompile/filters/errors/no-glob.d2,0:13:13-3:1:43",
"nodes": [
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:10:25",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:7:22-1:10:25",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
}
}
},
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:15:41",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"primary": {},
"value": {
"boolean": {
"range": "TestCompile/filters/errors/no-glob.d2,2:11:37-2:15:41",
"value": true
}
}
}
}
]
}
}
}
}
}
]
}
],
"edges": null
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:5:5",
"value": [
{
"string": "jacob",
"raw_string": "jacob"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:11:11",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:5:5",
"value": [
{
"string": "jacob",
"raw_string": "jacob"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:6:6-0:11:11",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-3:1:43",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:11:11",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:0:0-0:5:5",
"value": [
{
"string": "jacob",
"raw_string": "jacob"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,0:6:6-0:11:11",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "TestCompile/filters/errors/no-glob.d2,0:13:13-3:1:43",
"nodes": [
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:10:25",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:1:16-1:5:20",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,1:7:22-1:10:25",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
}
}
},
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:15:41",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,2:1:27-2:9:35",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"primary": {},
"value": {
"boolean": {
"range": "TestCompile/filters/errors/no-glob.d2,2:11:37-2:15:41",
"value": true
}
}
}
}
]
}
}
}
}
}
]
},
{
"name": "jasmine",
"composite": {
"fields": [
{
"name": "style",
"composite": {
"fields": null,
"edges": null
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:8:53-5:13:58",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:13:58",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:7:52",
"value": [
{
"string": "jasmine",
"raw_string": "jasmine"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:8:53-5:13:58",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-8:1:94",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:13:58",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:7:52",
"value": [
{
"string": "jasmine",
"raw_string": "jasmine"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:8:53-5:13:58",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "TestCompile/filters/errors/no-glob.d2,5:15:60-8:1:94",
"nodes": [
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,6:2:64-6:12:74",
"ampersand": true,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,6:3:65-6:7:69",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,6:3:65-6:7:69",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,6:9:71-6:12:74",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
}
}
},
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:17:92",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:10:85",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:10:85",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"primary": {},
"value": {
"boolean": {
"range": "TestCompile/filters/errors/no-glob.d2,7:12:87-7:17:92",
"value": false
}
}
}
}
]
}
}
}
}
}
]
}
],
"edges": null
},
"references": [
{
"string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:7:52",
"value": [
{
"string": "jasmine",
"raw_string": "jasmine"
}
]
},
"key_path": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:13:58",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:7:52",
"value": [
{
"string": "jasmine",
"raw_string": "jasmine"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:8:53-5:13:58",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"context": {
"edge": null,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-8:1:94",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:13:58",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:0:45-5:7:52",
"value": [
{
"string": "jasmine",
"raw_string": "jasmine"
}
]
}
},
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,5:8:53-5:13:58",
"value": [
{
"string": "style",
"raw_string": "style"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "TestCompile/filters/errors/no-glob.d2,5:15:60-8:1:94",
"nodes": [
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,6:2:64-6:12:74",
"ampersand": true,
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,6:3:65-6:7:69",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,6:3:65-6:7:69",
"value": [
{
"string": "fill",
"raw_string": "fill"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,6:9:71-6:12:74",
"value": [
{
"string": "red",
"raw_string": "red"
}
]
}
}
}
},
{
"map_key": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:17:92",
"key": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:10:85",
"path": [
{
"unquoted_string": {
"range": "TestCompile/filters/errors/no-glob.d2,7:2:77-7:10:85",
"value": [
{
"string": "multiple",
"raw_string": "multiple"
}
]
}
}
]
},
"primary": {},
"value": {
"boolean": {
"range": "TestCompile/filters/errors/no-glob.d2,7:12:87-7:17:92",
"value": false
}
}
}
}
]
}
}
}
}
}
]
}
],
"edges": null
}