]> Cypherpunks repositories - gostls13.git/commitdiff
gofix: trivial rewrite for template.ParseFiles
authorRob Pike <r@golang.org>
Thu, 24 Nov 2011 04:17:41 +0000 (20:17 -0800)
committerRob Pike <r@golang.org>
Thu, 24 Nov 2011 04:17:41 +0000 (20:17 -0800)
Also warn about uses of Set.

R=rsc
CC=golang-dev
https://golang.org/cl/5436051

src/cmd/gofix/Makefile
src/cmd/gofix/template.go [new file with mode: 0644]
src/cmd/gofix/template_test.go [new file with mode: 0644]

index 2887d5bd53e90f1f10b059beb525cea35d9e36a9..6ff489dcb1451cfea8ec565aa0f41d0146af5a6b 100644 (file)
@@ -31,6 +31,7 @@ GOFILES=\
        sorthelpers.go\
        sortslice.go\
        stringssplit.go\
+       template.go\
        typecheck.go\
        url.go\
 
diff --git a/src/cmd/gofix/template.go b/src/cmd/gofix/template.go
new file mode 100644 (file)
index 0000000..89100bc
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "go/ast"
+)
+
+func init() {
+       register(templateFix)
+}
+
+var templateFix = fix{
+       "template",
+       "2011-11-22",
+       template,
+       `Rewrite calls to template.ParseFile to template.ParseFiles
+
+http://codereview.appspot.com/5433048
+`,
+}
+
+var templateSetGlobals = []string{
+       "ParseSetFiles",
+       "ParseSetGlob",
+       "ParseTemplateFiles",
+       "ParseTemplateGlob",
+       "Set",
+       "SetMust",
+}
+
+var templateSetMethods = []string{
+       "ParseSetFiles",
+       "ParseSetGlob",
+       "ParseTemplateFiles",
+       "ParseTemplateGlob",
+}
+
+var templateTypeConfig = &TypeConfig{
+       Type: map[string]*Type{
+               "template.Template": &Type{
+                       Method: map[string]string{
+                               "Funcs":      "func() *template.Template",
+                               "Delims":     "func() *template.Template",
+                               "Parse":      "func() (*template.Template, error)",
+                               "ParseFile":  "func() (*template.Template, error)",
+                               "ParseInSet": "func() (*template.Template, error)",
+                       },
+               },
+               "template.Set": &Type{
+                       Method: map[string]string{
+                               "ParseSetFiles":      "func() (*template.Set, error)",
+                               "ParseSetGlob":       "func() (*template.Set, error)",
+                               "ParseTemplateFiles": "func() (*template.Set, error)",
+                               "ParseTemplateGlob":  "func() (*template.Set, error)",
+                       },
+               },
+       },
+
+       Func: map[string]string{
+               "template.New":     "*template.Template",
+               "template.Must":    "(*template.Template, error)",
+               "template.SetMust": "(*template.Set, error)",
+       },
+}
+
+func template(f *ast.File) bool {
+       if !imports(f, "text/template") && !imports(f, "html/template") {
+               return false
+       }
+
+       fixed := false
+
+       typeof, _ := typecheck(templateTypeConfig, f)
+
+       // Now update the names used by importers.
+       walk(f, func(n interface{}) {
+               if sel, ok := n.(*ast.SelectorExpr); ok {
+                       // Reference to top-level function ParseFile.
+                       if isPkgDot(sel, "template", "ParseFile") {
+                               sel.Sel.Name = "ParseFiles"
+                               fixed = true
+                               return
+                       }
+                       // Reference to ParseFiles method.
+                       if typeof[sel.X] == "*template.Template" && sel.Sel.Name == "ParseFile" {
+                               sel.Sel.Name = "ParseFiles"
+                               fixed = true
+                               return
+                       }
+                       // The Set type and its functions are now gone.
+                       for _, name := range templateSetGlobals {
+                               if isPkgDot(sel, "template", name) {
+                                       warn(sel.Pos(), "reference to template.%s must be fixed manually", name)
+                                       return
+                               }
+                       }
+                       // The methods of Set are now gone.
+                       for _, name := range templateSetMethods {
+                               if typeof[sel.X] == "*template.Set" && sel.Sel.Name == name {
+                                       warn(sel.Pos(), "reference to template.*Set.%s must be fixed manually", name)
+                                       return
+                               }
+                       }
+               }
+       })
+
+       return fixed
+}
diff --git a/src/cmd/gofix/template_test.go b/src/cmd/gofix/template_test.go
new file mode 100644 (file)
index 0000000..f713a29
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func init() {
+       addTestCases(templateTests, template)
+}
+
+var templateTests = []testCase{
+       {
+               Name: "template.0",
+               In: `package main
+
+import (
+       "text/template"
+)
+
+func f() {
+       template.ParseFile(a)
+       var t template.Template
+       x, y := template.ParseFile()
+       template.New("x").Funcs(m).ParseFile(a) // chained method
+       // Output should complain about these as functions or methods.
+       var s *template.Set
+       s.ParseSetFiles(a)
+       template.ParseSetGlob(a)
+       s.ParseTemplateFiles(a)
+       template.ParseTemplateGlob(a)
+       x := template.SetMust(a())
+}
+`,
+               Out: `package main
+
+import (
+       "text/template"
+)
+
+func f() {
+       template.ParseFiles(a)
+       var t template.Template
+       x, y := template.ParseFiles()
+       template.New("x").Funcs(m).ParseFiles(a) // chained method
+       // Output should complain about these as functions or methods.
+       var s *template.Set
+       s.ParseSetFiles(a)
+       template.ParseSetGlob(a)
+       s.ParseTemplateFiles(a)
+       template.ParseTemplateGlob(a)
+       x := template.SetMust(a())
+}
+`,
+       },
+}