Skip to content

Commit

Permalink
d2ir: Prevent globs from overriding any fields set by non globs
Browse files Browse the repository at this point in the history
  • Loading branch information
nhooyr committed Aug 17, 2023
1 parent d50f707 commit 7269541
Show file tree
Hide file tree
Showing 77 changed files with 3,722 additions and 903 deletions.
32 changes: 16 additions & 16 deletions d2compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,21 +322,21 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
}
for _, fr := range f.References {
if fr.Primary() {
if fr.Context.Key.Value.Map != nil {
obj.Map = fr.Context.Key.Value.Map
if fr.Context_.Key.Value.Map != nil {
obj.Map = fr.Context_.Key.Value.Map
}
}
r := d2graph.Reference{
Key: fr.KeyPath,
KeyPathIndex: fr.KeyPathIndex(),

MapKey: fr.Context.Key,
MapKeyEdgeIndex: fr.Context.EdgeIndex(),
Scope: fr.Context.Scope,
ScopeAST: fr.Context.ScopeAST,
MapKey: fr.Context_.Key,
MapKeyEdgeIndex: fr.Context_.EdgeIndex(),
Scope: fr.Context_.Scope,
ScopeAST: fr.Context_.ScopeAST,
}
if fr.Context.ScopeMap != nil && !d2ir.IsVar(fr.Context.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context.ScopeMap))
if fr.Context_.ScopeMap != nil && !d2ir.IsVar(fr.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context_.ScopeMap))
r.ScopeObj = obj.Graph.Root.EnsureChild(scopeObjIDA)
}
obj.References = append(obj.References, r)
Expand Down Expand Up @@ -725,14 +725,14 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
edge.Label.MapKey = e.LastPrimaryKey()
for _, er := range e.References {
r := d2graph.EdgeReference{
Edge: er.Context.Edge,
MapKey: er.Context.Key,
MapKeyEdgeIndex: er.Context.EdgeIndex(),
Scope: er.Context.Scope,
ScopeAST: er.Context.ScopeAST,
}
if er.Context.ScopeMap != nil && !d2ir.IsVar(er.Context.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context.ScopeMap))
Edge: er.Context_.Edge,
MapKey: er.Context_.Key,
MapKeyEdgeIndex: er.Context_.EdgeIndex(),
Scope: er.Context_.Scope,
ScopeAST: er.Context_.ScopeAST,
}
if er.Context_.ScopeMap != nil && !d2ir.IsVar(er.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context_.ScopeMap))
r.ScopeObj = edge.Src.Graph.Root.EnsureChild(scopeObjIDA)
}
edge.References = append(edge.References, r)
Expand Down
42 changes: 34 additions & 8 deletions d2ir/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ type compiler struct {
// Used to prevent field globs causing infinite loops.
globRefContextStack []*RefContext
// Used to check whether ampersands are allowed in the current map.
mapRefContextStack []*RefContext
mapRefContextStack []*RefContext
lazyGlobBeingApplied bool
}

type CompileOptions struct {
Expand All @@ -65,8 +66,8 @@ func Compile(ast *d2ast.Map, opts *CompileOptions) (*Map, error) {
}
m := &Map{}
m.initRoot()
m.parent.(*Field).References[0].Context.Scope = ast
m.parent.(*Field).References[0].Context.ScopeAST = ast
m.parent.(*Field).References[0].Context_.Scope = ast
m.parent.(*Field).References[0].Context_.ScopeAST = ast

c.pushImportStack(&d2ast.Import{
Path: []*d2ast.StringBox{d2ast.RawStringBox(ast.GetRange().Path, true)},
Expand Down Expand Up @@ -99,7 +100,7 @@ func (c *compiler) overlayClasses(m *Map) {

for _, lf := range layers.Fields {
if lf.Map() == nil || lf.Primary() != nil {
c.errorf(lf.References[0].Context.Key, "invalid layer")
c.errorf(lf.References[0].Context_.Key, "invalid layer")
continue
}
l := lf.Map()
Expand Down Expand Up @@ -353,7 +354,7 @@ func (c *compiler) resolveSubstitution(vars *Map, substitution *d2ast.Substituti

func (c *compiler) overlay(base *Map, f *Field) {
if f.Map() == nil || f.Primary() != nil {
c.errorf(f.References[0].Context.Key, "invalid %s", NodeBoardKind(f))
c.errorf(f.References[0].Context_.Key, "invalid %s", NodeBoardKind(f))
return
}
base = base.CopyBase(f)
Expand Down Expand Up @@ -512,7 +513,9 @@ func (c *compiler) compileKey(refctx *RefContext) {
if oldFields != refctx.ScopeMap.FieldCountRecursive() || oldEdges != refctx.ScopeMap.EdgeCountRecursive() {
for _, gctx2 := range c.globContexts() {
// println(d2format.Format(gctx2.refctx.Key), d2format.Format(refctx.Key))
c.lazyGlobBeingApplied = true
c.compileKey(gctx2.refctx)
c.lazyGlobBeingApplied = false
}
}
}
Expand Down Expand Up @@ -600,6 +603,9 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
}

if refctx.Key.Primary.Unbox() != nil {
if c.ignoreLazyGlob(f) {
return
}
f.Primary_ = &Scalar{
parent: f,
Value: refctx.Key.Primary.Unbox(),
Expand Down Expand Up @@ -686,6 +692,9 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
}
}
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
if c.ignoreLazyGlob(f) {
return
}
// If the link is a board, we need to transform it into an absolute path.
if f.Name == "link" {
c.compileLink(refctx)
Expand All @@ -697,6 +706,17 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
}
}

// Whether the current lazy glob being applied should not override the field
// if already set by a non glob key.
func (c *compiler) ignoreLazyGlob(n Node) bool {
if c.lazyGlobBeingApplied && n.Primary() != nil {
if ref := n.SecondLastPrimaryRef(); ref != nil && !ref.DueToGlob() {
return true
}
}
return false
}

func (c *compiler) updateLinks(m *Map) {
for _, f := range m.Fields {
if f.Name == "link" {
Expand Down Expand Up @@ -841,10 +861,10 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
}
for _, e := range ea {
e.References = append(e.References, &EdgeReference{
Context: refctx,
Context_: refctx,
})
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Src, refctx)
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Dst, refctx)
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Src, refctx, c)
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Dst, refctx, c)
}
} else {
var err error
Expand All @@ -865,6 +885,9 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
c.compileField(e.Map_, refctx.Key.EdgeKey, refctx)
} else {
if refctx.Key.Primary.Unbox() != nil {
if c.ignoreLazyGlob(e) {
return
}
e.Primary_ = &Scalar{
parent: e,
Value: refctx.Key.Primary.Unbox(),
Expand All @@ -883,6 +906,9 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
c.compileMap(e.Map_, refctx.Key.Value.Map, refctx.ScopeAST)
c.mapRefContextStack = c.mapRefContextStack[:len(c.mapRefContextStack)-1]
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
if c.ignoreLazyGlob(e) {
return
}
e.Primary_ = &Scalar{
parent: e,
Value: refctx.Key.Value.ScalarBox().Unbox(),
Expand Down
Loading

0 comments on commit 7269541

Please sign in to comment.