reimplement
This commit is contained in:
parent
757f292a20
commit
09d1ec6314
8 changed files with 244 additions and 180 deletions
|
|
@ -78,6 +78,7 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph {
|
|||
ir = ir.Copy(nil).(*d2ir.Map)
|
||||
// c.preprocessSeqDiagrams(ir)
|
||||
c.compileMap(g.Root, ir)
|
||||
c.nullify(g)
|
||||
if len(c.err.Errors) == 0 {
|
||||
c.validateKeys(g.Root, ir)
|
||||
}
|
||||
|
|
@ -244,7 +245,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
|
|||
}
|
||||
|
||||
for _, e := range m.Edges {
|
||||
c.compileEdge(obj, e)
|
||||
c.compileEdge(obj, e, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -303,11 +304,6 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
|
|||
}
|
||||
}
|
||||
|
||||
if f.Primary() != nil {
|
||||
if _, ok := f.Primary().Value.(*d2ast.Null); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
obj = obj.EnsureChild(d2graphIDA([]string{f.Name}))
|
||||
|
||||
if f.Primary() != nil {
|
||||
|
|
@ -708,12 +704,13 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
|
||||
func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge, m *d2ir.Map) {
|
||||
if e.Primary() != nil {
|
||||
if _, ok := e.Primary().Value.(*d2ast.Null); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
edge, err := obj.Connect(d2graphIDA(e.ID.SrcPath), d2graphIDA(e.ID.DstPath), e.ID.SrcArrow, e.ID.DstArrow, "")
|
||||
if err != nil {
|
||||
c.errorf(e.References[0].AST(), err.Error())
|
||||
|
|
@ -844,6 +841,14 @@ func (c *compiler) compileArrowheads(edge *d2graph.Edge, f *d2ir.Field) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *compiler) nullify(g *d2graph.Graph) {
|
||||
for _, obj := range g.Objects {
|
||||
if len(obj.References) > 0 && obj.References[len(obj.References)-1].Nulled() {
|
||||
g.DeleteObject(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add more, e.g. C, bash
|
||||
var ShortToFullLanguageAliases = map[string]string{
|
||||
"md": "markdown",
|
||||
|
|
|
|||
|
|
@ -3001,6 +3001,39 @@ a
|
|||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("implicit", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tca := []struct {
|
||||
name string
|
||||
skip bool
|
||||
run func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "connection",
|
||||
run: func(t *testing.T) {
|
||||
g := assertCompile(t, `
|
||||
x -> y
|
||||
y: null
|
||||
`, "")
|
||||
assert.Equal(t, 1, len(g.Objects))
|
||||
assert.Equal(t, 0, len(g.Edges))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tca {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if tc.skip {
|
||||
t.SkipNow()
|
||||
}
|
||||
tc.run(t)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func assertCompile(t *testing.T, text string, expErr string) *d2graph.Graph {
|
||||
|
|
|
|||
|
|
@ -73,6 +73,28 @@ func (g *Graph) RootBoard() *Graph {
|
|||
return g
|
||||
}
|
||||
|
||||
// DeleteObject deletes an object along with all its descendants.
|
||||
// It also deletes all edges connected to it or a descendant.
|
||||
func (g *Graph) DeleteObject(obj *Object) {
|
||||
for i, obj2 := range g.Objects {
|
||||
if obj == obj2 {
|
||||
g.Objects = append(g.Objects[:i], g.Objects[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
obj.Parent.removeChild(obj)
|
||||
|
||||
for i, e := range g.Edges {
|
||||
if e.Src == obj || e.Dst == obj {
|
||||
g.Edges = append(g.Edges[:i], g.Edges[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ch := range obj.ChildrenArray {
|
||||
g.DeleteObject(ch)
|
||||
}
|
||||
}
|
||||
|
||||
type LayoutGraph func(context.Context, *Graph) error
|
||||
|
||||
// TODO consider having different Scalar types
|
||||
|
|
@ -193,6 +215,10 @@ type Reference struct {
|
|||
ScopeAST *d2ast.Map `json:"-"`
|
||||
}
|
||||
|
||||
func (r *Reference) Nulled() bool {
|
||||
return r.MapKey != nil && r.MapKey.Value.Null != nil
|
||||
}
|
||||
|
||||
func (r Reference) MapKeyEdgeDest() bool {
|
||||
return r.Key == r.MapKey.Edges[r.MapKeyEdgeIndex].Dst
|
||||
}
|
||||
|
|
@ -785,39 +811,6 @@ func (obj *Object) ensureChildEdge(ida []string) *Object {
|
|||
return obj
|
||||
}
|
||||
|
||||
// DeleteChild deletes a child from the graph.
|
||||
// If it has connections or children, those will also be deleted (recursively)
|
||||
// func (obj *Object) DeleteChild(ida []string) error {
|
||||
// if len(ida) == 0 {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// _, is := ReservedKeywordHolders[ida[0]]
|
||||
// if len(ida) == 1 && !is {
|
||||
// _, ok := ReservedKeywords[ida[0]]
|
||||
// if ok {
|
||||
// return obj
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// id := ida[0]
|
||||
// ida = ida[1:]
|
||||
//
|
||||
// if id == "_" {
|
||||
// return obj.Parent.EnsureChild(ida)
|
||||
// }
|
||||
//
|
||||
// child, ok := obj.Children[strings.ToLower(id)]
|
||||
// if !ok {
|
||||
// child = obj.newObject(id)
|
||||
// }
|
||||
//
|
||||
// if len(ida) >= 1 {
|
||||
// return child.EnsureChild(ida)
|
||||
// }
|
||||
// return child
|
||||
// }
|
||||
|
||||
// EnsureChild grabs the child by ids or creates it if it does not exist including all
|
||||
// intermediate nodes.
|
||||
func (obj *Object) EnsureChild(ida []string) *Object {
|
||||
|
|
|
|||
|
|
@ -156,18 +156,12 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext)
|
|||
return
|
||||
}
|
||||
|
||||
if f.Primary() != nil {
|
||||
// null only applies if it's the appearance
|
||||
if _, ok := f.Primary().Value.(*d2ast.Null); ok {
|
||||
f.Primary_ = nil
|
||||
}
|
||||
}
|
||||
|
||||
if refctx.Key.Primary.Unbox() != nil {
|
||||
f.Primary_ = &Scalar{
|
||||
parent: f,
|
||||
Value: refctx.Key.Primary.Unbox(),
|
||||
}
|
||||
|
||||
}
|
||||
if refctx.Key.Value.Array != nil {
|
||||
a := &Array{
|
||||
|
|
|
|||
14
d2ir/d2ir.go
14
d2ir/d2ir.go
|
|
@ -786,6 +786,20 @@ func (m *Map) GetEdges(eid *EdgeID) []*Edge {
|
|||
return ea
|
||||
}
|
||||
|
||||
func (m *Map) DeleteEdge(eid *EdgeID) *Edge {
|
||||
if eid == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, e := range m.Edges {
|
||||
if e.ID.Match(eid) {
|
||||
m.Edges = append(m.Edges[:i], m.Edges[i+1:]...)
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) (*Edge, error) {
|
||||
if ParentEdge(m) != nil {
|
||||
return nil, d2parser.Errorf(refctx.Edge, "cannot create edge inside edge")
|
||||
|
|
|
|||
133
testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json
generated
vendored
133
testdata/d2compiler/TestCompile2/nulls/basic/edge.exp.json
generated
vendored
|
|
@ -132,138 +132,7 @@
|
|||
"zIndex": 0
|
||||
},
|
||||
"edges": null,
|
||||
"objects": [
|
||||
{
|
||||
"id": "a",
|
||||
"id_val": "a",
|
||||
"references": [
|
||||
{
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:0:1-1:1:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "a",
|
||||
"raw_string": "a"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path_index": 0,
|
||||
"map_key_edge_index": 0
|
||||
},
|
||||
{
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:1:9-2:2:10",
|
||||
"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/nulls/basic/edge.d2,1:5:6-1:6:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,1:5:6-1:6:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path_index": 0,
|
||||
"map_key_edge_index": 0
|
||||
},
|
||||
{
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/basic/edge.d2,2:6:14-2:7:15",
|
||||
"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
|
||||
}
|
||||
]
|
||||
"objects": null
|
||||
},
|
||||
"err": null
|
||||
}
|
||||
|
|
|
|||
156
testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json
generated
vendored
Normal file
156
testdata/d2compiler/TestCompile2/nulls/implicit/connection.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
{
|
||||
"graph": {
|
||||
"name": "",
|
||||
"isFolderOnly": false,
|
||||
"ast": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,0:0:0-3:0:16",
|
||||
"nodes": [
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:6:7",
|
||||
"edges": [
|
||||
{
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:6:7",
|
||||
"src": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "x",
|
||||
"raw_string": "x"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:5:6-1:6:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:5:6-1:6:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "y",
|
||||
"raw_string": "y"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
}
|
||||
],
|
||||
"primary": {},
|
||||
"value": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:7:15",
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:1:9",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:0:8-2:1:9",
|
||||
"value": [
|
||||
{
|
||||
"string": "y",
|
||||
"raw_string": "y"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"null": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,2:3:11-2:7:15"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"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": "x",
|
||||
"id_val": "x",
|
||||
"references": [
|
||||
{
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile2/nulls/implicit/connection.d2,1:0:1-1:1:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "x",
|
||||
"raw_string": "x"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path_index": 0,
|
||||
"map_key_edge_index": 0
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"label": {
|
||||
"value": "x"
|
||||
},
|
||||
"labelDimensions": {
|
||||
"width": 0,
|
||||
"height": 0
|
||||
},
|
||||
"style": {},
|
||||
"near_key": null,
|
||||
"shape": {
|
||||
"value": "rectangle"
|
||||
},
|
||||
"direction": {
|
||||
"value": ""
|
||||
},
|
||||
"constraint": null
|
||||
},
|
||||
"zIndex": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"err": null
|
||||
}
|
||||
2
testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json
generated
vendored
2
testdata/d2compiler/TestCompile2/nulls/reappear/shape.exp.json
generated
vendored
|
|
@ -172,7 +172,7 @@
|
|||
],
|
||||
"attributes": {
|
||||
"label": {
|
||||
"value": "a"
|
||||
"value": ""
|
||||
},
|
||||
"labelDimensions": {
|
||||
"width": 0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue