Merge pull request #1254 from alixander/improper-classes

"class" and "style" compiler validation
This commit is contained in:
Alexander Wang 2023-04-27 12:04:44 -07:00 committed by GitHub
commit 40467a3842
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 349 additions and 285 deletions

View file

@ -6,6 +6,7 @@
- ELK self loops get distributed around the object instead of stacking [#1232](https://github.com/terrastruct/d2/pull/1232) - ELK self loops get distributed around the object instead of stacking [#1232](https://github.com/terrastruct/d2/pull/1232)
- ELK preserves order of objects in cycles [#1235](https://github.com/terrastruct/d2/pull/1235) - ELK preserves order of objects in cycles [#1235](https://github.com/terrastruct/d2/pull/1235)
- Improper usages of `class` and `style` get error messages [#1254](https://github.com/terrastruct/d2/pull/1254)
#### Bugfixes ⛑️ #### Bugfixes ⛑️

View file

@ -197,6 +197,7 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
return return
} else if f.Name == "style" { } else if f.Name == "style" {
if f.Map() == nil { if f.Map() == nil {
c.errorf(f.LastRef().AST(), `"style" expected to be set to a map, or contain an additional keyword like "style.opacity: 0.4"`)
return return
} }
c.compileStyle(&obj.Attributes, f.Map()) c.compileStyle(&obj.Attributes, f.Map())
@ -481,6 +482,10 @@ func (c *compiler) compileStyle(attrs *d2graph.Attributes, m *d2ir.Map) {
} }
func (c *compiler) compileStyleField(attrs *d2graph.Attributes, f *d2ir.Field) { func (c *compiler) compileStyleField(attrs *d2graph.Attributes, f *d2ir.Field) {
if _, ok := d2graph.StyleKeywords[strings.ToLower(f.Name)]; !ok {
c.errorf(f.LastRef().AST(), `invalid style keyword: "%s"`, f.Name)
return
}
if f.Primary() == nil { if f.Primary() == nil {
return return
} }

View file

@ -1678,6 +1678,24 @@ x.a.b`,
}`, }`,
expErr: `d2/testdata/d2compiler/TestCompile/no-nested-columns-class.d2:3:5: class fields cannot have children`, expErr: `d2/testdata/d2compiler/TestCompile/no-nested-columns-class.d2:3:5: class fields cannot have children`,
}, },
{
name: "improper-class-ref",
text: `myobj.class.style.stroke-dash: 3`,
expErr: `d2/testdata/d2compiler/TestCompile/improper-class-ref.d2:1:7: "class" must be the last part of the key`,
},
{
name: "tail-style",
text: `myobj.style: 3`,
expErr: `d2/testdata/d2compiler/TestCompile/tail-style.d2:1:7: "style" expected to be set to a map, or contain an additional keyword like "style.opacity: 0.4"`,
},
{
name: "bad-style-nesting",
text: `myobj.style.style.stroke-dash: 3`,
expErr: `d2/testdata/d2compiler/TestCompile/bad-style-nesting.d2:1:13: invalid style keyword: "style"`,
},
{ {
name: "edge_to_style", name: "edge_to_style",

View file

@ -671,6 +671,10 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext) (*Field,
head = strings.ToLower(head) head = strings.ToLower(head)
} }
if head == "class" && i < len(kp.Path)-1 {
return nil, d2parser.Errorf(kp.Path[i].Unbox(), `"class" must be the last part of the key`)
}
if head == "_" { if head == "_" {
return nil, d2parser.Errorf(kp.Path[i].Unbox(), `parent "_" can only be used in the beginning of paths, e.g. "_.x"`) return nil, d2parser.Errorf(kp.Path[i].Unbox(), `parent "_" can only be used in the beginning of paths, e.g. "_.x"`)
} }

View file

@ -244,7 +244,7 @@ Android: {
web -> twitter fe web -> twitter fe
timeline scorer: "Timeline\nScorer" { timeline scorer: "Timeline\nScorer" {
style.fill "#ffdef1" style.fill: "#ffdef1"
} }
home ranker: Home Ranker home ranker: Home Ranker
@ -283,7 +283,7 @@ prediction service2: Prediction Service {
icon: https://cdn-icons-png.flaticon.com/512/6461/6461819.png icon: https://cdn-icons-png.flaticon.com/512/6461/6461819.png
} }
home scorer: Home Scorer { home scorer: Home Scorer {
style.fill "#ffdef1" style.fill: "#ffdef1"
} }
manhattan: Manhattan manhattan: Manhattan
memcache: Memcache { memcache: Memcache {
@ -766,7 +766,7 @@ Android: {
web -> twitter fe web -> twitter fe
timeline scorer: "Timeline\nScorer" { timeline scorer: "Timeline\nScorer" {
style.fill "#ffdef1" style.fill: "#ffdef1"
} }
home ranker: Home Ranker home ranker: Home Ranker
@ -805,7 +805,7 @@ prediction service2: Prediction Service {
icon: https://cdn-icons-png.flaticon.com/512/6461/6461819.png icon: https://cdn-icons-png.flaticon.com/512/6461/6461819.png
} }
home scorer: Home Scorer { home scorer: Home Scorer {
style.fill "#ffdef1" style.fill: "#ffdef1"
} }
manhattan: Manhattan manhattan: Manhattan
memcache: Memcache { memcache: Memcache {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

View file

@ -0,0 +1,12 @@
{
"graph": null,
"err": {
"ioerr": null,
"errs": [
{
"range": "d2/testdata/d2compiler/TestCompile/bad-style-nesting.d2,0:12:12-0:17:17",
"errmsg": "d2/testdata/d2compiler/TestCompile/bad-style-nesting.d2:1:13: invalid style keyword: \"style\""
}
]
}
}

View file

@ -0,0 +1,12 @@
{
"graph": null,
"err": {
"ioerr": null,
"errs": [
{
"range": "d2/testdata/d2compiler/TestCompile/improper-class-ref.d2,0:6:6-0:11:11",
"errmsg": "d2/testdata/d2compiler/TestCompile/improper-class-ref.d2:1:7: \"class\" must be the last part of the key"
}
]
}
}

12
testdata/d2compiler/TestCompile/tail-style.exp.json generated vendored Normal file
View file

@ -0,0 +1,12 @@
{
"graph": null,
"err": {
"ioerr": null,
"errs": [
{
"range": "d2/testdata/d2compiler/TestCompile/tail-style.d2,0:6:6-0:11:11",
"errmsg": "d2/testdata/d2compiler/TestCompile/tail-style.d2:1:7: \"style\" expected to be set to a map, or contain an additional keyword like \"style.opacity: 0.4\""
}
]
}
}