// 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}} }