Name the inline drawGroup refusal as a binding's reference fence, beside the cycle fence

This commit is contained in:
2026-09-28 10:37:26 +02:00
committed by Lillem4n
parent 224cf12fdd
commit 01a60d06f1
3 changed files with 19 additions and 24 deletions
+8 -15
View File
@@ -200,14 +200,10 @@ func inlineScope(n node, label string) nodeScope {
// NewTemplate and FakeStruct share; its fields are where they differ.
type binding struct {
scope nodeScope
// link binds the references: a loaded tree's relative to each category's folder, an
// inline node's from the root alone.
link func() error
// noCycles refuses a reference cycle, which only a loaded tree can close: nothing
// references an inline node.
noCycles func() error
// typedByGo marks a struct's columns, whose datatypes its Go types set and checkField
// proves, so checkColumns skips them.
link func() error
// A loaded tree's cycle fence; an inline node's refusal of a drawGroup at its root.
referenceFence func() error
// checkField proves a struct's columns instead.
typedByGo bool
}
@@ -221,7 +217,7 @@ func treeBinding(root map[string]node) binding {
}
return linkRefs(root)
},
noCycles: func() error { return checkNoCycles(root) },
referenceFence: func() error { return checkNoCycles(root) },
}
}
@@ -229,10 +225,8 @@ func (b binding) bind() error {
if err := b.link(); err != nil {
return err
}
if b.noCycles != nil {
if err := b.noCycles(); err != nil {
return err
}
if err := b.referenceFence(); err != nil {
return err
}
if !b.typedByGo {
if err := checkColumns(b.scope); err != nil {
@@ -244,8 +238,7 @@ func (b binding) bind() error {
// checkRenders runs the per-node fences over a scope, each over the whole scope
// before the next, so which of several broken nodes is reported does not depend on
// the walk. Its walks terminate only where nothing renders itself, so run it over a
// loaded tree after checkNoCycles.
// the walk. Its walks terminate only where nothing renders itself.
func checkRenders(s nodeScope) error {
mem := renderCounts{}
if err := s(func(path string, n node) error { return repeatCheck(path, n, mem) }); err != nil {
+2 -1
View File
@@ -58,7 +58,8 @@ tags and any other caller read one.
`New` proves the loaded tree acyclic, an inline node is a finite tree of its own, and
nothing in the tree can reference it, so no render of it reaches itself. Every other
fence runs over both, from one `binding.bind`, except that struct tags leave column
agreement to their Go types.
agreement to their Go types, and an inline node refuses a `drawGroup` at its root,
which nothing can name.
## An inline template that does not compile is misuse (exit 2), including a reference that resolves to nothing
+9 -8
View File
@@ -146,17 +146,18 @@ func inputValue(input string) (any, error) {
return raw, nil
}
// inlineBinding binds an inline node against root, naming its nodes from label.
func inlineBinding(n node, label string, root map[string]node) binding {
scope := inlineScope(n, label)
return binding{scope: scope, link: func() error { return linkInline(n, label, scope, root) }}
}
func linkInline(n node, label string, scope nodeScope, root map[string]node) error {
if t, isTemplate := n.(*template); isTemplate && t.drawGroup != "" {
return fmt.Errorf("%s: drawGroup %q names nothing, since nothing can reference an inline template; drop it", label, t.drawGroup)
return binding{
scope: scope,
link: func() error { return linkNodeRefs(scope, root) },
referenceFence: func() error {
if t, isTemplate := n.(*template); isTemplate && t.drawGroup != "" {
return fmt.Errorf("%s: drawGroup %q names nothing, since nothing can reference an inline template; drop it", label, t.drawGroup)
}
return nil
},
}
return linkNodeRefs(scope, root)
}
// linkNodeRefs binds the references in an inline node's templates against the