From 1b4dff0f6923f5d7004d47de5ebeba3758074c86 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 28 Jul 2011 16:19:16 -0700 Subject: [PATCH] exp/template: simplify the helper functions - create a pair of "Must" functions, one for templates, one for sets - regularize the return values of the parsers so they can be wrapped by Must - delete all the old Must functions and methods. R=golang-dev, gri, r CC=golang-dev https://golang.org/cl/4826052 --- src/pkg/exp/template/exec_test.go | 8 +- src/pkg/exp/template/helper.go | 235 +++++++++-------------------- src/pkg/exp/template/parse.go | 8 +- src/pkg/exp/template/parse_test.go | 3 +- src/pkg/exp/template/set.go | 5 +- src/pkg/exp/template/set_test.go | 37 +++-- 6 files changed, 101 insertions(+), 195 deletions(-) diff --git a/src/pkg/exp/template/exec_test.go b/src/pkg/exp/template/exec_test.go index 05f3b90ebf..d9b8afbcd2 100644 --- a/src/pkg/exp/template/exec_test.go +++ b/src/pkg/exp/template/exec_test.go @@ -72,7 +72,7 @@ var tVal = &T{ Empty4: &U{"UinEmpty"}, PI: newInt(23), PSI: newIntSlice(21, 22, 23), - Tmpl: New("x").MustParse("test template"), // "x" is the value of .X + Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X } // Helpers for creation. @@ -359,7 +359,7 @@ func testExecute(execTests []execTest, set *Set, t *testing.T) { funcs := FuncMap{"zeroArgs": zeroArgs, "oneArg": oneArg, "typeOf": typeOf} for _, test := range execTests { tmpl := New(test.name).Funcs(funcs) - err := tmpl.ParseInSet(test.input, set) + _, err := tmpl.ParseInSet(test.input, set) if err != nil { t.Errorf("%s: parse error: %s", test.name, err) continue @@ -394,7 +394,7 @@ func TestExecute(t *testing.T) { func TestExecuteError(t *testing.T) { b := new(bytes.Buffer) tmpl := New("error") - err := tmpl.Parse("{{.EPERM true}}") + _, err := tmpl.Parse("{{.EPERM true}}") if err != nil { t.Fatalf("parse error: %s", err) } @@ -487,7 +487,7 @@ func TestTree(t *testing.T) { }, } set := new(Set) - err := set.Parse(treeTemplate) + _, err := set.Parse(treeTemplate) if err != nil { t.Fatal("parse error:", err) } diff --git a/src/pkg/exp/template/helper.go b/src/pkg/exp/template/helper.go index cf50a3082f..4187897171 100644 --- a/src/pkg/exp/template/helper.go +++ b/src/pkg/exp/template/helper.go @@ -15,42 +15,12 @@ import ( // Functions and methods to parse a single template. -// MustParse parses the template definition string to construct an internal -// representation of the template for execution. -// It panics if the template cannot be parsed. -func (t *Template) MustParse(text string) *Template { - if err := t.Parse(text); err != nil { - panic(err) - } - return t -} - -// ParseFile reads the template definition from a file and parses it to -// construct an internal representation of the template for execution. -func (t *Template) ParseFile(filename string) os.Error { - b, err := ioutil.ReadFile(filename) +// Must is a helper that wraps a call to a function returning (*Template, os.Error) +// and panics if the error is non-nil. It is intended for use in variable initializations +// such as +// var t = template.Must(template.Parse("text")) +func Must(t *Template, err os.Error) *Template { if err != nil { - return err - } - return t.Parse(string(b)) -} - -// ParseFileInSet is the same as ParseFile except that function bindings -// are checked against those in the set and the template is added -// to the set. -func (t *Template) ParseFileInSet(filename string, set *Set) os.Error { - b, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - return t.ParseInSet(string(b), set) -} - -// MustParseFile reads the template definition from a file and parses it to -// construct an internal representation of the template for execution. -// It panics if the file cannot be read or the template cannot be parsed. -func (t *Template) MustParseFile(filename string) *Template { - if err := t.ParseFile(filename); err != nil { panic(err) } return t @@ -60,31 +30,47 @@ func (t *Template) MustParseFile(filename string) *Template { // the named file. The template name is the base name of the file. func ParseFile(filename string) (*Template, os.Error) { t := New(filepath.Base(filename)) - return t, t.ParseFile(filename) + return t.ParseFile(filename) } -// ParseFileInSet creates a new Template and parses the template +// parseFileInSet creates a new Template and parses the template // definition from the named file. The template name is the base name // of the file. It also adds the template to the set. Function bindings are -//checked against those in the set. -func ParseFileInSet(filename string, set *Set) (*Template, os.Error) { +// checked against those in the set. +func parseFileInSet(filename string, set *Set) (*Template, os.Error) { t := New(filepath.Base(filename)) - return t, t.ParseFileInSet(filename, set) + return t.parseFileInSet(filename, set) } -// MustParseFile creates a new Template and parses the template definition -// from the named file. The template name is the base name of the file. -// It panics if the file cannot be read or the template cannot be parsed. -func MustParseFile(filename string) *Template { - return New(filepath.Base(filename)).MustParseFile(filename) +// ParseFile reads the template definition from a file and parses it to +// construct an internal representation of the template for execution. +func (t *Template) ParseFile(filename string) (*Template, os.Error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return t, err + } + return t.Parse(string(b)) +} + +// parseFileInSet is the same as ParseFile except that function bindings +// are checked against those in the set and the template is added +// to the set. +func (t *Template) parseFileInSet(filename string, set *Set) (*Template, os.Error) { + b, err := ioutil.ReadFile(filename) + if err != nil { + return t, err + } + return t.ParseInSet(string(b), set) } // Functions and methods to parse a set. -// MustParse parses a string into a set of named templates. -// It panics if the set cannot be parsed. -func (s *Set) MustParse(text string) *Set { - if err := s.Parse(text); err != nil { +// SetMust is a helper that wraps a call to a function returning (*Set, os.Error) +// and panics if the error is non-nil. It is intended for use in variable initializations +// such as +// var s = template.SetMust(template.ParseSetFile("file")) +func SetMust(s *Set, err os.Error) *Set { + if err != nil { panic(err) } return s @@ -93,70 +79,47 @@ func (s *Set) MustParse(text string) *Set { // ParseFile parses the named files into a set of named templates. // Each file must be parseable by itself. Parsing stops if an error is // encountered. -func (s *Set) ParseFile(filenames ...string) os.Error { +func (s *Set) ParseFile(filenames ...string) (*Set, os.Error) { for _, filename := range filenames { b, err := ioutil.ReadFile(filename) if err != nil { - return err + return s, err } - err = s.Parse(string(b)) + _, err = s.Parse(string(b)) if err != nil { - return err - } - } - return nil -} - -// MustParseFile parses the named file into a set of named templates. -// Each file must be parseable by itself. -// MustParseFile panics if any file cannot be read or parsed. -func (s *Set) MustParseFile(filenames ...string) *Set { - err := s.ParseFile(filenames...) - if err != nil { - panic(err) - } - return s -} - -// ParseSetFile creates a new Set and parses the set definition from the -// named files. Each file must be individually parseable. -func ParseSetFile(filenames ...string) (set *Set, err os.Error) { - s := new(Set) - var b []byte - for _, filename := range filenames { - b, err = ioutil.ReadFile(filename) - if err != nil { - return - } - err = s.Parse(string(b)) - if err != nil { - return + return s, err } } return s, nil } -// MustParseSetFile creates a new Set and parses the set definition from the +// ParseSetFile creates a new Set and parses the set definition from the // named files. Each file must be individually parseable. -// MustParseSetFile panics if any file cannot be read or parsed. -func MustParseSetFile(filenames ...string) *Set { - s, err := ParseSetFile(filenames...) - if err != nil { - panic(err) +func ParseSetFile(filenames ...string) (*Set, os.Error) { + s := new(Set) + for _, filename := range filenames { + b, err := ioutil.ReadFile(filename) + if err != nil { + return s, err + } + _, err = s.Parse(string(b)) + if err != nil { + return s, err + } } - return s + return s, nil } // ParseFiles parses the set definition from the files identified by the // pattern. The pattern is processed by filepath.Glob and must match at // least one file. -func (s *Set) ParseFiles(pattern string) os.Error { +func (s *Set) ParseFiles(pattern string) (*Set, os.Error) { filenames, err := filepath.Glob(pattern) if err != nil { - return err + return s, err } if len(filenames) == 0 { - return fmt.Errorf("pattern matches no files: %#q", pattern) + return s, fmt.Errorf("pattern matches no files: %#q", pattern) } return s.ParseFile(filenames...) } @@ -165,26 +128,13 @@ func (s *Set) ParseFiles(pattern string) os.Error { // files identified by the pattern. The pattern is processed by filepath.Glob // and must match at least one file. func ParseSetFiles(pattern string) (*Set, os.Error) { - set := new(Set) - err := set.ParseFiles(pattern) + set, err := new(Set).ParseFiles(pattern) if err != nil { - return nil, err + return set, err } return set, nil } -// MustParseSetFiles creates a new Set and parses the set definition from the -// files identified by the pattern. The pattern is processed by filepath.Glob. -// MustParseSetFiles panics if the pattern is invalid or a matched file cannot be -// read or parsed. -func MustParseSetFiles(pattern string) *Set { - set, err := ParseSetFiles(pattern) - if err != nil { - panic(err) - } - return set -} - // Functions and methods to parse stand-alone template files into a set. // ParseTemplateFile parses the named template files and adds @@ -197,24 +147,14 @@ func MustParseSetFiles(pattern string) *Set { // individual templates, which are then added to the set. // Each file must be parseable by itself. Parsing stops if an error is // encountered. -func (s *Set) ParseTemplateFile(filenames ...string) os.Error { +func (s *Set) ParseTemplateFile(filenames ...string) (*Set, os.Error) { for _, filename := range filenames { - _, err := ParseFileInSet(filename, s) + _, err := parseFileInSet(filename, s) if err != nil { - return err + return s, err } } - return nil -} - -// MustParseTemplateFile is like ParseTemplateFile but -// panics if there is an error. -func (s *Set) MustParseTemplateFile(filenames ...string) *Set { - err := s.ParseTemplateFile(filenames...) - if err != nil { - panic(err) - } - return s + return s, nil } // ParseTemplateFiles parses the template files matched by the @@ -227,28 +167,18 @@ func (s *Set) MustParseTemplateFile(filenames ...string) *Set { // individual templates, which are then added to the set. // Each file must be parseable by itself. Parsing stops if an error is // encountered. -func (s *Set) ParseTemplateFiles(pattern string) os.Error { +func (s *Set) ParseTemplateFiles(pattern string) (*Set, os.Error) { filenames, err := filepath.Glob(pattern) if err != nil { - return err + return s, err } for _, filename := range filenames { - _, err := ParseFileInSet(filename, s) + _, err := parseFileInSet(filename, s) if err != nil { - return err + return s, err } } - return nil -} - -// MustParseTemplateFile is like ParseTemplateFiles but -// panics if there is an error. -func (s *Set) MustParseTemplateFiles(pattern string) *Set { - err := s.ParseTemplateFiles(pattern) - if err != nil { - panic(err) - } - return s + return s, nil } // ParseTemplateFile creates a set by parsing the named files, @@ -266,25 +196,15 @@ func ParseTemplateFile(filenames ...string) (*Set, os.Error) { for _, filename := range filenames { t, err := ParseFile(filename) if err != nil { - return nil, err + return set, err } if err := set.add(t); err != nil { - return nil, err + return set, err } } return set, nil } -// MustParseTemplateFile is like ParseTemplateFile but -// panics if there is an error. -func MustParseTemplateFile(filenames ...string) *Set { - set, err := ParseTemplateFile(filenames...) - if err != nil { - panic(err) - } - return set -} - // ParseTemplateFiles creates a set by parsing the files matched // by the pattern, each of which defines a single template. Each // template will named the base name of its file. @@ -296,30 +216,19 @@ func MustParseTemplateFile(filenames ...string) *Set { // Each file must be parseable by itself. Parsing stops if an error is // encountered. func ParseTemplateFiles(pattern string) (*Set, os.Error) { + set := new(Set) filenames, err := filepath.Glob(pattern) if err != nil { - return nil, err + return set, err } - set := new(Set) for _, filename := range filenames { t, err := ParseFile(filename) if err != nil { - return nil, err + return set, err } if err := set.add(t); err != nil { - return nil, err + return set, err } } return set, nil } - -// MustParseTemplateFiles is like ParseTemplateFiles but -// panics if there is a parse error or other problem -// constructing the set. -func MustParseTemplateFiles(pattern string) *Set { - set, err := ParseTemplateFiles(pattern) - if err != nil { - panic(err) - } - return set -} diff --git a/src/pkg/exp/template/parse.go b/src/pkg/exp/template/parse.go index aa75eb8d94..8a0b51eafd 100644 --- a/src/pkg/exp/template/parse.go +++ b/src/pkg/exp/template/parse.go @@ -610,25 +610,25 @@ func (t *Template) atEOF() bool { // Parse parses the template definition string to construct an internal // representation of the template for execution. -func (t *Template) Parse(s string) (err os.Error) { +func (t *Template) Parse(s string) (tmpl *Template, err os.Error) { defer t.recover(&err) t.startParse(t.set, lex(t.name, s)) t.parse(true) t.stopParse() - return + return t, nil } // ParseInSet parses the template definition string to construct an internal // representation of the template for execution. It also adds the template // to the set. // Function bindings are checked against those in the set. -func (t *Template) ParseInSet(s string, set *Set) (err os.Error) { +func (t *Template) ParseInSet(s string, set *Set) (tmpl *Template, err os.Error) { defer t.recover(&err) t.startParse(set, lex(t.name, s)) t.parse(true) t.stopParse() t.addToSet(set) - return nil + return t, nil } // addToSet adds the template to the set, verifying it's not being double-assigned. diff --git a/src/pkg/exp/template/parse_test.go b/src/pkg/exp/template/parse_test.go index 6b4ca1989f..fb8956a465 100644 --- a/src/pkg/exp/template/parse_test.go +++ b/src/pkg/exp/template/parse_test.go @@ -230,8 +230,7 @@ var parseTests = []parseTest{ func TestParse(t *testing.T) { for _, test := range parseTests { - tmpl := New(test.name) - err := tmpl.Parse(test.input) + tmpl, err := New(test.name).Parse(test.input) switch { case err == nil && !test.ok: t.Errorf("%q: expected error; got none", test.name) diff --git a/src/pkg/exp/template/set.go b/src/pkg/exp/template/set.go index dc64b4c9c3..a685e996de 100644 --- a/src/pkg/exp/template/set.go +++ b/src/pkg/exp/template/set.go @@ -99,7 +99,8 @@ func (s *Set) recover(errp *os.Error) { // multiple times for a given set, adding the templates defined in the string // to the set. If a template is redefined, the element in the set is // overwritten with the new definition. -func (s *Set) Parse(text string) (err os.Error) { +func (s *Set) Parse(text string) (set *Set, err os.Error) { + set = s s.init() defer s.recover(&err) lex := lex("set", text) @@ -130,5 +131,5 @@ func (s *Set) Parse(text string) (err os.Error) { t.addToSet(s) s.tmpl[t.name] = t } - return nil + return s, nil } diff --git a/src/pkg/exp/template/set_test.go b/src/pkg/exp/template/set_test.go index c42d97a07b..4f2d76e207 100644 --- a/src/pkg/exp/template/set_test.go +++ b/src/pkg/exp/template/set_test.go @@ -38,8 +38,7 @@ var setParseTests = []setParseTest{ func TestSetParse(t *testing.T) { for _, test := range setParseTests { - set := new(Set) - err := set.Parse(test.input) + set, err := new(Set).Parse(test.input) switch { case err == nil && !test.ok: t.Errorf("%q: expected error; got none", test.name) @@ -54,6 +53,9 @@ func TestSetParse(t *testing.T) { } continue } + if set == nil { + continue + } if len(set.tmpl) != len(test.names) { t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(set.tmpl)) continue @@ -101,12 +103,11 @@ const setText2 = ` func TestSetExecute(t *testing.T) { // Declare a set with a couple of templates first. - set := new(Set) - err := set.Parse(setText1) + set, err := new(Set).Parse(setText1) if err != nil { t.Fatalf("error parsing set: %s", err) } - err = set.Parse(setText2) + _, err = set.Parse(setText2) if err != nil { t.Fatalf("error parsing set: %s", err) } @@ -114,12 +115,11 @@ func TestSetExecute(t *testing.T) { } func TestSetParseFile(t *testing.T) { - set := new(Set) - err := set.ParseFile("DOES NOT EXIST") + set, err := new(Set).ParseFile("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - err = set.ParseFile("testdata/file1.tmpl", "testdata/file2.tmpl") + _, err = set.ParseFile("testdata/file1.tmpl", "testdata/file2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } @@ -139,16 +139,15 @@ func TestParseSetFile(t *testing.T) { } func TestSetParseFiles(t *testing.T) { - set := new(Set) - err := set.ParseFiles("DOES NOT EXIST") + set, err := new(Set).ParseFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - err = set.ParseFiles("[x") + _, err = set.ParseFiles("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - err = set.ParseFiles("testdata/file*.tmpl") + _, err = set.ParseFiles("testdata/file*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } @@ -172,16 +171,15 @@ func TestParseSetFiles(t *testing.T) { } var templateFileExecTests = []execTest{ - {"teset", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\ntemplate2\n", 0, true}, + {"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\ntemplate2\n", 0, true}, } func TestSetParseTemplateFile(t *testing.T) { - set := new(Set) - err := set.ParseTemplateFile("DOES NOT EXIST") + set, err := ParseTemplateFile("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - err = set.ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") + _, err = set.ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) } @@ -201,16 +199,15 @@ func TestParseTemplateFile(t *testing.T) { } func TestSetParseTemplateFiles(t *testing.T) { - set := new(Set) - err := set.ParseTemplateFiles("DOES NOT EXIST") + set, err := ParseTemplateFiles("DOES NOT EXIST") if err == nil { t.Error("expected error for non-existent file; got none") } - err = set.ParseTemplateFiles("[x") + _, err = set.ParseTemplateFiles("[x") if err == nil { t.Error("expected error for bad pattern; got none") } - err = set.ParseTemplateFiles("testdata/tmpl*.tmpl") + _, err = set.ParseTemplateFiles("testdata/tmpl*.tmpl") if err != nil { t.Fatalf("error parsing files: %v", err) }