blob: 7135d8edf11ebfe6cfd016257dd503c3f02dc88f [file] [log] [blame]
// 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 }{
{"URL", "URL"},
{"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.
var skip interface{}
urlWalk := func(n interface{}) {
if n == skip {
skip = nil
return
}
// Is it an identifier?
if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" {
ident.Name = "url_"
return
}
// Parameter and result names.
if fn, ok := n.(*ast.FuncType); ok {
fixed = urlDoFields(fn.Params) || fixed
fixed = urlDoFields(fn.Results) || fixed
}
// U{url: ...} is likely a struct field.
if kv, ok := n.(*ast.KeyValueExpr); ok {
if ident, ok := kv.Key.(*ast.Ident); ok && ident.Name == "url" {
skip = ident
}
}
}
// Fix up URL code and add import, at most once.
fix := func() {
if fixed {
return
}
walkBeforeAfter(f, urlWalk, nop)
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
}