--- /dev/null
+// 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(strconvFix)
+}
+
+var strconvFix = fix{
+ "strconv",
+ "2011-12-01",
+ strconvFn,
+ `Convert to new strconv API.
+
+http://codereview.appspot.com/5434095
+http://codereview.appspot.com/5434069
+`,
+}
+
+func strconvFn(f *ast.File) bool {
+ if !imports(f, "strconv") {
+ return false
+ }
+
+ fixed := false
+
+ walk(f, func(n interface{}) {
+ // Rename functions.
+ call, ok := n.(*ast.CallExpr)
+ if !ok || len(call.Args) < 1 {
+ return
+ }
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok || !isTopName(sel.X, "strconv") {
+ return
+ }
+ change := func(name string) {
+ fixed = true
+ sel.Sel.Name = name
+ }
+ add := func(s string) {
+ call.Args = append(call.Args, expr(s))
+ }
+ switch sel.Sel.Name {
+ case "Atob":
+ change("ParseBool")
+ case "Atof32":
+ change("ParseFloat")
+ add("32") // bitSize
+ warn(call.Pos(), "rewrote strconv.Atof32(_) to strconv.ParseFloat(_, 32) but return value must be converted to float32")
+ case "Atof64":
+ change("ParseFloat")
+ add("64") // bitSize
+ case "AtofN":
+ change("ParseFloat")
+ case "Atoi":
+ // Atoi stayed as a convenience wrapper.
+ case "Atoi64":
+ change("ParseInt")
+ add("10") // base
+ add("64") // bitSize
+ case "Atoui":
+ change("ParseUint")
+ add("10") // base
+ add("0") // bitSize
+ warn(call.Pos(), "rewrote strconv.Atoui(_) to strconv.ParseUint(_, 10, 0) but return value must be converted to uint")
+ case "Atoui64":
+ change("ParseUint")
+ add("10") // base
+ add("64") // bitSize
+ case "Btoa":
+ change("FormatBool")
+ case "Btoi64":
+ change("ParseInt")
+ add("64") // bitSize
+ case "Btoui64":
+ change("ParseUint")
+ add("64") // bitSize
+ case "Ftoa32":
+ change("FormatFloat")
+ call.Args[0] = strconvRewrite("float32", "float64", call.Args[0])
+ add("32") // bitSize
+ case "Ftoa64":
+ change("FormatFloat")
+ add("64") // bitSize
+ case "FtoaN":
+ change("FormatFloat")
+ case "Itoa":
+ // Itoa stayed as a convenience wrapper.
+ case "Itoa64":
+ change("FormatInt")
+ add("10") // base
+ case "Itob":
+ change("FormatInt")
+ call.Args[0] = strconvRewrite("int", "int64", call.Args[0])
+ case "Itob64":
+ change("FormatInt")
+ case "Uitoa":
+ change("FormatUint")
+ call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
+ add("10") // base
+ case "Uitoa64":
+ change("FormatUint")
+ add("10") // base
+ case "Uitob":
+ change("FormatUint")
+ call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
+ case "Uitob64":
+ change("FormatUint")
+ }
+ })
+ return fixed
+}
+
+// rewrite from type t1 to type t2
+// If the expression x is of the form t1(_), use t2(_). Otherwise use t2(x).
+func strconvRewrite(t1, t2 string, x ast.Expr) ast.Expr {
+ if call, ok := x.(*ast.CallExpr); ok && isTopName(call.Fun, t1) {
+ call.Fun.(*ast.Ident).Name = t2
+ return x
+ }
+ return &ast.CallExpr{Fun: ast.NewIdent(t2), Args: []ast.Expr{x}}
+}
--- /dev/null
+// 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(strconvTests, strconvFn)
+}
+
+var strconvTests = []testCase{
+ {
+ Name: "strconv.0",
+ In: `package main
+
+import "strconv"
+
+func f() {
+ foo.Atob("abc")
+
+ strconv.Atob("true")
+ strconv.Btoa(false)
+
+ strconv.Atof32("1.2")
+ strconv.Atof64("1.2")
+ strconv.AtofN("1.2", 64)
+ strconv.Ftoa32(1.2, 'g', 17)
+ strconv.Ftoa64(1.2, 'g', 17)
+ strconv.FtoaN(1.2, 'g', 17, 64)
+
+ strconv.Atoi("3")
+ strconv.Atoi64("3")
+ strconv.Btoi64("1234", 5)
+
+ strconv.Atoui("3")
+ strconv.Atoui64("3")
+ strconv.Btoui64("1234", 5)
+
+ strconv.Itoa(123)
+ strconv.Itoa64(1234)
+ strconv.Itob(123, 5)
+ strconv.Itob64(1234, 5)
+
+ strconv.Uitoa(123)
+ strconv.Uitoa64(1234)
+ strconv.Uitob(123, 5)
+ strconv.Uitob64(1234, 5)
+
+ strconv.Uitoa(uint(x))
+ strconv.Uitoa(f(x))
+}
+`,
+ Out: `package main
+
+import "strconv"
+
+func f() {
+ foo.Atob("abc")
+
+ strconv.ParseBool("true")
+ strconv.FormatBool(false)
+
+ strconv.ParseFloat("1.2", 32)
+ strconv.ParseFloat("1.2", 64)
+ strconv.ParseFloat("1.2", 64)
+ strconv.FormatFloat(float64(1.2), 'g', 17, 32)
+ strconv.FormatFloat(1.2, 'g', 17, 64)
+ strconv.FormatFloat(1.2, 'g', 17, 64)
+
+ strconv.Atoi("3")
+ strconv.ParseInt("3", 10, 64)
+ strconv.ParseInt("1234", 5, 64)
+
+ strconv.ParseUint("3", 10, 0)
+ strconv.ParseUint("3", 10, 64)
+ strconv.ParseUint("1234", 5, 64)
+
+ strconv.Itoa(123)
+ strconv.FormatInt(1234, 10)
+ strconv.FormatInt(int64(123), 5)
+ strconv.FormatInt(1234, 5)
+
+ strconv.FormatUint(uint64(123), 10)
+ strconv.FormatUint(1234, 10)
+ strconv.FormatUint(uint64(123), 5)
+ strconv.FormatUint(1234, 5)
+
+ strconv.FormatUint(uint64(x), 10)
+ strconv.FormatUint(uint64(f(x)), 10)
+}
+`,
+ },
+}