edge cases

This commit is contained in:
Alexander Wang 2023-07-11 17:33:01 -07:00
parent 92d87b553f
commit af69e6f626
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
5 changed files with 769 additions and 12 deletions

View file

@ -3290,6 +3290,21 @@ a -> b: ${x}
assert.Equal(t, "im a var", g.Edges[0].Label.Value)
},
},
{
name: "edge-map",
run: func(t *testing.T) {
g := assertCompile(t, `
vars: {
x: im a var
}
a -> b: {
target-arrowhead.label: ${x}
}
`, "")
assert.Equal(t, 1, len(g.Edges))
assert.Equal(t, "im a var", g.Edges[0].DstArrowhead.Label.Value)
},
},
{
name: "quoted-var",
run: func(t *testing.T) {
@ -3325,6 +3340,23 @@ y: "hey ${x}"
assert.Equal(t, `hey "hi"`, g.Objects[0].Label.Value)
},
},
{
name: "parent-scope",
run: func(t *testing.T) {
g := assertCompile(t, `
vars: {
x: im root var
}
a: {
vars: {
b: im nested var
}
hi: ${x}
}
`, "")
assert.Equal(t, "im root var", g.Objects[1].Label.Value)
},
},
}
for _, tc := range tca {
@ -3538,6 +3570,19 @@ hi: ${x.z}
`, `d2/testdata/d2compiler/TestCompile2/vars/errors/nested-missing.d2:7:1: could not resolve variable "x.z"`)
},
},
{
name: "out-of-scope",
run: func(t *testing.T) {
assertCompile(t, `
a: {
vars: {
x: hey
}
}
hi: ${x}
`, `d2/testdata/d2compiler/TestCompile2/vars/errors/out-of-scope.d2:7:1: could not resolve variable "x"`)
},
},
{
name: "edge",
run: func(t *testing.T) {

View file

@ -114,17 +114,31 @@ func (c *compiler) compileSubstitutions(m *Map, varsStack []*Map) {
if e.Primary() != nil {
c.resolveSubstitutions(varsStack, e.LastRef().AST(), e.Primary())
}
if e.Map() != nil {
c.compileSubstitutions(e.Map(), varsStack)
}
}
}
func (c *compiler) resolveSubstitutions(varsStack []*Map, node d2ast.Node, scalar *Scalar) {
subbed := false
var subbed bool
var resolvedField *Field
switch s := scalar.Value.(type) {
case *d2ast.UnquotedString:
for i, box := range s.Value {
if box.Substitution != nil {
resolvedField := c.resolveSubstitution(varsStack[0], node, box.Substitution)
for _, vars := range varsStack {
resolvedField = c.resolveSubstitution(vars, box.Substitution)
if resolvedField != nil {
break
}
}
if resolvedField != nil {
if resolvedField.Composite != nil {
c.errorf(node, `cannot reference map variable "%s"`, strings.Join(box.Substitution.IDA(), "."))
return
}
// If lone and unquoted, replace with value of sub
if len(s.Value) == 1 {
scalar.Value = resolvedField.Primary().Value
@ -132,6 +146,9 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node d2ast.Node, scala
s.Value[i].String = go2.Pointer(resolvedField.Primary().String())
subbed = true
}
} else {
c.errorf(node, `could not resolve variable "%s"`, strings.Join(box.Substitution.IDA(), "."))
return
}
}
}
@ -141,10 +158,22 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node d2ast.Node, scala
case *d2ast.DoubleQuotedString:
for i, box := range s.Value {
if box.Substitution != nil {
resolvedField := c.resolveSubstitution(varsStack[0], node, box.Substitution)
for _, vars := range varsStack {
resolvedField = c.resolveSubstitution(vars, box.Substitution)
if resolvedField != nil {
break
}
}
if resolvedField != nil {
if resolvedField.Composite != nil {
c.errorf(node, `cannot reference map variable "%s"`, strings.Join(box.Substitution.IDA(), "."))
return
}
s.Value[i].String = go2.Pointer(resolvedField.Primary().String())
subbed = true
} else {
c.errorf(node, `could not resolve variable "%s"`, strings.Join(box.Substitution.IDA(), "."))
return
}
}
}
@ -154,7 +183,7 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node d2ast.Node, scala
}
}
func (c *compiler) resolveSubstitution(vars *Map, node d2ast.Node, substitution *d2ast.Substitution) *Field {
func (c *compiler) resolveSubstitution(vars *Map, substitution *d2ast.Substitution) *Field {
var resolved *Field
for _, p := range substitution.Path {
if vars == nil {
@ -170,14 +199,7 @@ func (c *compiler) resolveSubstitution(vars *Map, node d2ast.Node, substitution
resolved = r
}
if resolved == nil {
c.errorf(node, `could not resolve variable "%s"`, strings.Join(substitution.IDA(), "."))
} else if resolved.Composite != nil {
c.errorf(node, `cannot reference map variable "%s"`, strings.Join(substitution.IDA(), "."))
} else {
return resolved
}
return nil
return resolved
}
func (c *compiler) overlayVars(base, overlay *Map) {

View file

@ -0,0 +1,350 @@
{
"graph": {
"name": "",
"isFolderOnly": false,
"ast": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,0:0:0-7:0:68",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,1:0:1-3:1:24",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,1:0:1-1:4:5",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,1:0:1-1:4:5",
"value": [
{
"string": "vars",
"raw_string": "vars"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,1:6:7-3:1:24",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,2:2:11-2:13:22",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,2:2:11-2:3:12",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,2:2:11-2:3:12",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,2:5:14-2:13:22",
"value": [
{
"string": "im a var",
"raw_string": "im a var"
}
]
}
}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-6:1:67",
"edges": [
{
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-4:6:31",
"src": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-4:1:26",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-4:1:26",
"value": [
{
"string": "a",
"raw_string": "a"
}
]
}
}
]
},
"src_arrow": "",
"dst": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:5:30-4:6:31",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:5:30-4:6:31",
"value": [
{
"string": "b",
"raw_string": "b"
}
]
}
}
]
},
"dst_arrow": ">"
}
],
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:8:33-6:1:67",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:2:37-5:30:65",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:2:37-5:24:59",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:2:37-5:18:53",
"value": [
{
"string": "target-arrowhead",
"raw_string": "target-arrowhead"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:19:54-5:24:59",
"value": [
{
"string": "label",
"raw_string": "label"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:26:61-5:27:62",
"value": [
{
"substitution": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:26:61-5:30:65",
"spread": false,
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,5:28:63-5:29:64",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
}
}
]
}
}
}
}
]
}
}
}
}
]
},
"root": {
"id": "",
"id_val": "",
"attributes": {
"label": {
"value": ""
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
},
"edges": [
{
"index": 0,
"isCurve": false,
"src_arrow": false,
"dst_arrow": true,
"dstArrowhead": {
"label": {
"value": "im a var"
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": null
},
"references": [
{
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": ""
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
}
],
"objects": [
{
"id": "a",
"id_val": "a",
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-4:1:26",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:0:25-4:1:26",
"value": [
{
"string": "a",
"raw_string": "a"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": "a"
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
},
{
"id": "b",
"id_val": "b",
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:5:30-4:6:31",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/edge-map.d2,4:5:30-4:6:31",
"value": [
{
"string": "b",
"raw_string": "b"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": "b"
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
}
]
},
"err": null
}

View file

@ -0,0 +1,329 @@
{
"graph": {
"name": "",
"isFolderOnly": false,
"ast": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,0:0:0-10:0:81",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,1:0:1-3:1:27",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,1:0:1-1:4:5",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,1:0:1-1:4:5",
"value": [
{
"string": "vars",
"raw_string": "vars"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,1:6:7-3:1:27",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,2:2:11-2:16:25",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,2:2:11-2:3:12",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,2:2:11-2:3:12",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,2:5:14-2:16:25",
"value": [
{
"string": "im root var",
"raw_string": "im root var"
}
]
}
}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:0:28-9:1:80",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:0:28-4:1:29",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:0:28-4:1:29",
"value": [
{
"string": "a",
"raw_string": "a"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:3:31-9:1:80",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,5:2:35-7:3:67",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,5:2:35-5:6:39",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,5:2:35-5:6:39",
"value": [
{
"string": "vars",
"raw_string": "vars"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,5:8:41-7:3:67",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,6:4:47-6:20:63",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,6:4:47-6:5:48",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,6:4:47-6:5:48",
"value": [
{
"string": "b",
"raw_string": "b"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,6:7:50-6:20:63",
"value": [
{
"string": "im nested var",
"raw_string": "im nested var"
}
]
}
}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:2:70-8:10:78",
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:2:70-8:4:72",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:2:70-8:4:72",
"value": [
{
"string": "hi",
"raw_string": "hi"
}
]
}
}
]
},
"primary": {},
"value": {
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:6:74-8:7:75",
"value": [
{
"substitution": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:6:74-8:10:78",
"spread": false,
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:8:76-8:9:77",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
}
}
]
}
}
}
}
]
}
}
}
}
]
},
"root": {
"id": "",
"id_val": "",
"attributes": {
"label": {
"value": ""
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
},
"edges": null,
"objects": [
{
"id": "a",
"id_val": "a",
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:0:28-4:1:29",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,4:0:28-4:1:29",
"value": [
{
"string": "a",
"raw_string": "a"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": -1
}
],
"attributes": {
"label": {
"value": "a"
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
},
{
"id": "hi",
"id_val": "hi",
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:2:70-8:4:72",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile2/vars/basic/parent-scope.d2,8:2:70-8:4:72",
"value": [
{
"string": "hi",
"raw_string": "hi"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": -1
}
],
"attributes": {
"label": {
"value": "im root var"
},
"labelDimensions": {
"width": 0,
"height": 0
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": null
},
"zIndex": 0
}
]
},
"err": null
}

View file

@ -0,0 +1,11 @@
{
"graph": null,
"err": {
"errs": [
{
"range": "d2/testdata/d2compiler/TestCompile2/vars/errors/out-of-scope.d2,6:0:33-6:2:35",
"errmsg": "d2/testdata/d2compiler/TestCompile2/vars/errors/out-of-scope.d2:7:1: could not resolve variable \"x\""
}
]
}
}