summaryrefslogtreecommitdiff
path: root/src/cmd/fix/strconv.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/fix/strconv.go')
-rw-r--r--src/cmd/fix/strconv.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/cmd/fix/strconv.go b/src/cmd/fix/strconv.go
new file mode 100644
index 000000000..6cd69020b
--- /dev/null
+++ b/src/cmd/fix/strconv.go
@@ -0,0 +1,127 @@
+// 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}}
+}