fix: cr, add validation for near connectioins

This commit is contained in:
donglixiaoche 2023-03-22 13:43:25 +08:00
parent 72253e892f
commit 22cce86892
No known key found for this signature in database
GPG key ID: 3190E65EBAD6D6E2
4 changed files with 442 additions and 0 deletions

View file

@ -735,6 +735,20 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
c.errorf(obj.Attributes.NearKey, "constant near keys can only be set on root level shapes")
continue
}
descendantsMap := getNearDescendants(obj)
connectToOutside := false
for _, edge := range g.Edges {
if (descendantsMap[edge.Src] && !descendantsMap[edge.Dst]) ||
(!descendantsMap[edge.Src] && descendantsMap[edge.Dst]) {
connectToOutside = true
}
}
if connectToOutside {
c.errorf(obj.Attributes.NearKey, "a child of a near container cannot connect to outside")
continue
}
} else {
c.errorf(obj.Attributes.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.Attributes.NearKey), strings.Join(d2graph.NearConstantsArray, ", "))
continue
@ -743,6 +757,24 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
}
}
func getNearDescendants(nearObj *d2graph.Object) map[*d2graph.Object]bool {
descendantsMap := make(map[*d2graph.Object]bool)
var helper func(obj *d2graph.Object)
helper = func(obj *d2graph.Object) {
if obj.ChildrenArray != nil {
for _, child := range obj.ChildrenArray {
descendantsMap[child] = true
helper(child)
}
}
}
helper(nearObj)
return descendantsMap
}
func (c *compiler) validateBoardLinks(g *d2graph.Graph) {
for _, obj := range g.Objects {
if obj.Attributes.Link == nil {

View file

@ -1535,6 +1535,17 @@ d2/testdata/d2compiler/TestCompile/near-invalid.d2:14:9: near keys cannot be set
`,
expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:3:12: constant near keys cannot be set on connected shapes`,
},
{
name: "near_descendant_connect_to_outside",
text: `
x: {
near: top-left
y
}
x.y -> z
`,
expErr: "d2/testdata/d2compiler/TestCompile/near_descendant_connect_to_outside.d2:3:12: a child of a near container cannot connect to outside",
},
{
name: "nested_near_constant",

View file

@ -0,0 +1,387 @@
{
"graph": {
"name": "",
"isFolderOnly": false,
"ast": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,0:0:0-5:3:39",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:4:5-3:5:22",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:4:5-1:5:6",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:4:5-1:5:6",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
},
"primary": {},
"value": {
"map": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:7:8-3:4:21",
"nodes": [
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,2:5:15-2:6:16",
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,2:5:15-2:6:16",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,2:5:15-2:6:16",
"value": [
{
"string": "y",
"raw_string": "y"
}
]
}
}
]
},
"primary": {},
"value": {}
}
}
]
}
}
}
},
{
"map_key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:12:35",
"edges": [
{
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:12:35",
"src": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:8:31",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:5:28",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:6:29-4:7:30",
"value": [
{
"string": "y",
"raw_string": "y"
}
]
}
}
]
},
"src_arrow": "",
"dst": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:10:33-4:12:35",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:11:34-4:12:35",
"value": [
{
"string": "z",
"raw_string": "z"
}
]
}
}
]
},
"dst_arrow": ">"
}
],
"primary": {},
"value": {}
}
}
]
},
"root": {
"id": "",
"id_val": "",
"label_dimensions": {
"width": 0,
"height": 0
},
"attributes": {
"label": {
"value": ""
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": {
"value": ""
}
},
"zIndex": 0
},
"edges": [
{
"index": 0,
"minWidth": 0,
"minHeight": 0,
"label_dimensions": {
"width": 0,
"height": 0
},
"isCurve": false,
"src_arrow": false,
"dst_arrow": true,
"references": [
{
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": ""
},
"style": {},
"near_key": null,
"shape": {
"value": ""
},
"direction": {
"value": ""
},
"constraint": {
"value": ""
}
},
"zIndex": 0
}
],
"objects": [
{
"id": "x",
"id_val": "x",
"label_dimensions": {
"width": 0,
"height": 0
},
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:4:5-1:5:6",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,1:4:5-1:5:6",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": -1
},
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:8:31",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:5:28",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:6:29-4:7:30",
"value": [
{
"string": "y",
"raw_string": "y"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": "x"
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": {
"value": ""
}
},
"zIndex": 0
},
{
"id": "y",
"id_val": "y",
"label_dimensions": {
"width": 0,
"height": 0
},
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,2:5:15-2:6:16",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,2:5:15-2:6:16",
"value": [
{
"string": "y",
"raw_string": "y"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": -1
},
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:8:31",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:4:27-4:5:28",
"value": [
{
"string": "x",
"raw_string": "x"
}
]
}
},
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:6:29-4:7:30",
"value": [
{
"string": "y",
"raw_string": "y"
}
]
}
}
]
},
"key_path_index": 1,
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": "y"
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": {
"value": ""
}
},
"zIndex": 0
},
{
"id": "z",
"id_val": "z",
"label_dimensions": {
"width": 0,
"height": 0
},
"references": [
{
"key": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:10:33-4:12:35",
"path": [
{
"unquoted_string": {
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_conent_to_outside.d2,4:11:34-4:12:35",
"value": [
{
"string": "z",
"raw_string": "z"
}
]
}
}
]
},
"key_path_index": 0,
"map_key_edge_index": 0
}
],
"attributes": {
"label": {
"value": "z"
},
"style": {},
"near_key": null,
"shape": {
"value": "rectangle"
},
"direction": {
"value": ""
},
"constraint": {
"value": ""
}
},
"zIndex": 0
}
]
},
"err": null
}

View file

@ -0,0 +1,12 @@
{
"graph": null,
"err": {
"ioerr": null,
"errs": [
{
"range": "d2/testdata/d2compiler/TestCompile/near_descendant_connect_to_outside.d2,2:11:21-2:19:29",
"errmsg": "d2/testdata/d2compiler/TestCompile/near_descendant_connect_to_outside.d2:3:12: a child of a near container cannot connect to outside"
}
]
}
}