From: Rob Pike Date: Thu, 24 Nov 2011 04:17:41 +0000 (-0800) Subject: gofix: trivial rewrite for template.ParseFiles X-Git-Tag: weekly.2011-12-01~63 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=da62104169c7b31f8b2917b24232dd349b769c8f;p=gostls13.git gofix: trivial rewrite for template.ParseFiles Also warn about uses of Set. R=rsc CC=golang-dev https://golang.org/cl/5436051 --- diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile index 2887d5bd53..6ff489dcb1 100644 --- a/src/cmd/gofix/Makefile +++ b/src/cmd/gofix/Makefile @@ -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 index 0000000000..89100bc142 --- /dev/null +++ b/src/cmd/gofix/template.go @@ -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 index 0000000000..f713a2901e --- /dev/null +++ b/src/cmd/gofix/template_test.go @@ -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()) +} +`, + }, +}