Index: src/cmd/gofix/url.go |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/cmd/gofix/url.go |
@@ -0,0 +1,116 @@ |
+// 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 ( |
+ "fmt" |
+ "os" |
+ "go/ast" |
+) |
+ |
+var _ fmt.Stringer |
+var _ os.Error |
+ |
+var urlFix = fix{ |
+ "url", |
+ url, |
+ `Move the URL pieces of package http into a new package, url. |
+ |
+http://codereview.appspot.com/4893043 |
+`, |
+} |
+ |
+func init() { |
+ register(urlFix) |
+} |
+ |
+var urlRenames = []struct{ in, out string }{ |
+ {"ParseURL", "Parse"}, |
+ {"ParseURLReference", "ParseWithReference"}, |
+ {"ParseQuery", "ParseQuery"}, |
+ {"Values", "Values"}, |
+ {"URLEscape", "QueryEscape"}, |
+ {"URLUnescape", "QueryUnescape"}, |
+ {"URLError", "Error"}, |
+ {"URLEscapeError", "EscapeError"}, |
+} |
+ |
+func url(f *ast.File) bool { |
+ if imports(f, "url") || !imports(f, "http") { |
+ return false |
+ } |
+ |
+ fixed := false |
+ |
+ // Update URL code. |
+ urlWalk := func(n interface{}) { |
+ // Is it an identifier? |
+ if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" { |
+ ident.Name = "url_" |
+ return |
+ } |
+ // Find declared identifiers called url that might be confused. |
+ // TODO: Why does gofix not walk the Names in a ValueSpec? |
+ // TODO: Just a bug; fix later as it will have consequences. |
+ if valSpec, ok := n.(*ast.ValueSpec); ok { |
+ for _, ident := range valSpec.Names { |
+ if ident.Name == "url" { |
+ ident.Name = "url_" |
+ } |
+ } |
+ } |
+ // Parameter and result names. |
+ if fn, ok := n.(*ast.FuncType); ok { |
+ fixed = urlDoFields(fn.Params) || fixed |
+ fixed = urlDoFields(fn.Results) || fixed |
+ } |
+ } |
+ |
+ // Fix up URL code and add import, at most once. |
+ fix := func() { |
+ if fixed { |
+ return |
+ } |
+ walk(f, urlWalk) |
+ addImport(f, "url") |
+ fixed = true |
+ } |
+ |
+ walk(f, func(n interface{}) { |
+ // Rename functions and methods. |
+ if expr, ok := n.(ast.Expr); ok { |
+ for _, s := range urlRenames { |
+ if isPkgDot(expr, "http", s.in) { |
+ fix() |
+ expr.(*ast.SelectorExpr).X.(*ast.Ident).Name = "url" |
+ expr.(*ast.SelectorExpr).Sel.Name = s.out |
+ return |
+ } |
+ } |
+ } |
+ }) |
+ |
+ // Remove the http import if no longer needed. |
+ if fixed && !usesImport(f, "http") { |
+ deleteImport(f, "http") |
+ } |
+ |
+ return fixed |
+} |
+ |
+func urlDoFields(list *ast.FieldList) (fixed bool) { |
+ if list == nil { |
+ return |
+ } |
+ for _, field := range list.List { |
+ for _, ident := range field.Names { |
+ if ident.Name == "url" { |
+ fixed = true |
+ ident.Name = "url_" |
+ } |
+ } |
+ } |
+ return |
+} |