type Mode uint
const (
- ParseComments Mode = 1 << iota // parse comments and add them to AST
+ ParseComments Mode = 1 << iota // parse comments and add them to AST
+ DeferFuncCheck // defer type checking functions until template is executed
)
// Copy returns a copy of the Tree. Any parsing state is discarded.
func (t *Tree) term() Node {
switch token := t.nextNonSpace(); token.typ {
case itemIdentifier:
- if !t.hasFunction(token.val) {
+ checkFunc := t.Mode&DeferFuncCheck == 0
+ if checkFunc && !t.hasFunction(token.val) {
t.errorf("function %q not defined", token.val)
}
return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
}
}
+func TestDeferFuncCheck(t *testing.T) {
+ oldTextFormat := textFormat
+ textFormat = "%q"
+ defer func() { textFormat = oldTextFormat }()
+ tr := New("defer func check")
+ tr.Mode = DeferFuncCheck
+ tmpl, err := tr.Parse("{{fn 1 2}}", "", "", make(map[string]*Tree))
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ expected := "{{fn 1 2}}"
+ if result := tmpl.Root.String(); result != expected {
+ t.Errorf("got\n\t%v\nexpected\n\t%v", result, expected)
+ }
+}
+
type isEmptyTest struct {
name string
input string