Commit e6b33717 authored by Rob Pike's avatar Rob Pike

template: move the empty check into parse, which needs it when constructing

tree sets.

R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5449062
parent a5d30086
......@@ -13,35 +13,6 @@ import (
"text/template/parse"
)
type isEmptyTest struct {
name string
input string
empty bool
}
var isEmptyTests = []isEmptyTest{
{"empty", ``, true},
{"nonempty", `hello`, false},
{"spaces only", " \t\n \t\n", true},
{"definition", `{{define "x"}}something{{end}}`, true},
{"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
{"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
{"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
}
func TestIsEmpty(t *testing.T) {
for _, test := range isEmptyTests {
template, err := New("root").Parse(test.input)
if err != nil {
t.Errorf("%q: unexpected error: %v", test.name, err)
continue
}
if empty := isEmpty(template.Root); empty != test.empty {
t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
}
}
}
const (
noError = true
hasError = false
......
......@@ -7,6 +7,7 @@
package parse
import (
"bytes"
"fmt"
"runtime"
"strconv"
......@@ -177,10 +178,37 @@ func (t *Tree) Parse(s, leftDelim, rightDelim string, treeSet map[string]*Tree,
// add adds tree to the treeSet.
func (t *Tree) add(treeSet map[string]*Tree) {
if _, present := treeSet[t.Name]; present {
tree := treeSet[t.Name]
if tree == nil || IsEmptyTree(tree.Root) {
treeSet[t.Name] = t
return
}
if !IsEmptyTree(t.Root) {
t.errorf("template: multiple definition of template %q", t.Name)
}
treeSet[t.Name] = t
}
// IsEmptyTree reports whether this tree (node) is empty of everything but space.
func IsEmptyTree(n Node) bool {
switch n := n.(type) {
case *ActionNode:
case *IfNode:
case *ListNode:
for _, node := range n.Nodes {
if !IsEmptyTree(node) {
return false
}
}
return true
case *RangeNode:
case *TemplateNode:
case *TextNode:
return len(bytes.TrimSpace(n.Text)) == 0
case *WithNode:
default:
panic("unknown node: " + n.String())
}
return false
}
// parse is the top-level parser for a template, essentially the same
......
......@@ -257,3 +257,32 @@ func TestParse(t *testing.T) {
}
}
}
type isEmptyTest struct {
name string
input string
empty bool
}
var isEmptyTests = []isEmptyTest{
{"empty", ``, true},
{"nonempty", `hello`, false},
{"spaces only", " \t\n \t\n", true},
{"definition", `{{define "x"}}something{{end}}`, true},
{"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
{"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
{"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
}
func TestIsEmpty(t *testing.T) {
for _, test := range isEmptyTests {
tree, err := New("root").Parse(test.input, "", "", make(map[string]*Tree), nil)
if err != nil {
t.Errorf("%q: unexpected error: %v", test.name, err)
continue
}
if empty := IsEmptyTree(tree.Root); empty != test.empty {
t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
}
}
}
......@@ -5,7 +5,6 @@
package template
import (
"bytes"
"fmt"
"reflect"
"text/template/parse"
......@@ -198,8 +197,8 @@ func (t *Template) associate(new *Template) error {
}
name := new.name
if old := t.tmpl[name]; old != nil {
oldIsEmpty := isEmpty(old.Root)
newIsEmpty := isEmpty(new.Root)
oldIsEmpty := parse.IsEmptyTree(old.Root)
newIsEmpty := parse.IsEmptyTree(new.Root)
if !oldIsEmpty && !newIsEmpty {
return fmt.Errorf("template: redefinition of template %q", name)
}
......@@ -211,26 +210,3 @@ func (t *Template) associate(new *Template) error {
t.tmpl[name] = new
return nil
}
// isEmpty reports whether this tree (node) is empty of everything but space.
func isEmpty(n parse.Node) bool {
switch n := n.(type) {
case *parse.ActionNode:
case *parse.IfNode:
case *parse.ListNode:
for _, node := range n.Nodes {
if !isEmpty(node) {
return false
}
}
return true
case *parse.RangeNode:
case *parse.TemplateNode:
case *parse.TextNode:
return len(bytes.TrimSpace(n.Text)) == 0
case *parse.WithNode:
default:
panic("unknown node: " + n.String())
}
return false
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment