| // 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" |
| "strings" |
| ) |
| |
| func init() { |
| register(go1pkgrenameFix) |
| } |
| |
| var go1pkgrenameFix = fix{ |
| "go1rename", |
| "2011-11-08", |
| go1pkgrename, |
| `Rewrite imports for packages moved during transition to Go 1. |
| |
| http://codereview.appspot.com/5316078 |
| `, |
| } |
| |
| var go1PackageRenames = []struct{ old, new string }{ |
| {"asn1", "encoding/asn1"}, |
| {"big", "math/big"}, |
| {"cmath", "math/cmplx"}, |
| {"csv", "encoding/csv"}, |
| {"exec", "os/exec"}, |
| {"exp/template/html", "html/template"}, |
| {"gob", "encoding/gob"}, |
| {"http", "net/http"}, |
| {"http/cgi", "net/http/cgi"}, |
| {"http/fcgi", "net/http/fcgi"}, |
| {"http/httptest", "net/http/httptest"}, |
| {"http/pprof", "net/http/pprof"}, |
| {"json", "encoding/json"}, |
| {"mail", "net/mail"}, |
| {"rpc", "net/rpc"}, |
| {"rpc/jsonrpc", "net/rpc/jsonrpc"}, |
| {"scanner", "text/scanner"}, |
| {"smtp", "net/smtp"}, |
| {"syslog", "log/syslog"}, |
| {"tabwriter", "text/tabwriter"}, |
| {"template", "text/template"}, |
| {"template/parse", "text/template/parse"}, |
| {"rand", "math/rand"}, |
| {"url", "net/url"}, |
| {"utf16", "unicode/utf16"}, |
| {"utf8", "unicode/utf8"}, |
| {"xml", "encoding/xml"}, |
| |
| // go.crypto sub-repository |
| {"crypto/bcrypt", "code.google.com/p/go.crypto/bcrypt"}, |
| {"crypto/blowfish", "code.google.com/p/go.crypto/blowfish"}, |
| {"crypto/cast5", "code.google.com/p/go.crypto/cast5"}, |
| {"crypto/md4", "code.google.com/p/go.crypto/md4"}, |
| {"crypto/ocsp", "code.google.com/p/go.crypto/ocsp"}, |
| {"crypto/openpgp", "code.google.com/p/go.crypto/openpgp"}, |
| {"crypto/openpgp/armor", "code.google.com/p/go.crypto/openpgp/armor"}, |
| {"crypto/openpgp/elgamal", "code.google.com/p/go.crypto/openpgp/elgamal"}, |
| {"crypto/openpgp/errors", "code.google.com/p/go.crypto/openpgp/errors"}, |
| {"crypto/openpgp/packet", "code.google.com/p/go.crypto/openpgp/packet"}, |
| {"crypto/openpgp/s2k", "code.google.com/p/go.crypto/openpgp/s2k"}, |
| {"crypto/ripemd160", "code.google.com/p/go.crypto/ripemd160"}, |
| {"crypto/twofish", "code.google.com/p/go.crypto/twofish"}, |
| {"crypto/xtea", "code.google.com/p/go.crypto/xtea"}, |
| {"exp/ssh", "code.google.com/p/go.crypto/ssh"}, |
| |
| // go.image sub-repository |
| {"image/bmp", "code.google.com/p/go.image/bmp"}, |
| {"image/tiff", "code.google.com/p/go.image/tiff"}, |
| |
| // go.net sub-repository |
| {"net/dict", "code.google.com/p/go.net/dict"}, |
| {"net/websocket", "code.google.com/p/go.net/websocket"}, |
| {"exp/spdy", "code.google.com/p/go.net/spdy"}, |
| {"http/spdy", "code.google.com/p/go.net/spdy"}, |
| |
| // go.codereview sub-repository |
| {"encoding/git85", "code.google.com/p/go.codereview/git85"}, |
| {"patch", "code.google.com/p/go.codereview/patch"}, |
| |
| // exp |
| {"ebnf", "exp/ebnf"}, |
| {"go/types", "exp/types"}, |
| |
| // deleted |
| {"container/vector", ""}, |
| {"exp/datafmt", ""}, |
| {"go/typechecker", ""}, |
| {"old/netchan", ""}, |
| {"old/regexp", ""}, |
| {"old/template", ""}, |
| {"try", ""}, |
| } |
| |
| var go1PackageNameRenames = []struct{ newPath, old, new string }{ |
| {"html/template", "html", "template"}, |
| {"math/cmplx", "cmath", "cmplx"}, |
| } |
| |
| func go1pkgrename(f *ast.File) bool { |
| fixed := false |
| |
| // First update the imports. |
| for _, rename := range go1PackageRenames { |
| spec := importSpec(f, rename.old) |
| if spec == nil { |
| continue |
| } |
| if rename.new == "" { |
| warn(spec.Pos(), "package %q has been deleted in Go 1", rename.old) |
| continue |
| } |
| if rewriteImport(f, rename.old, rename.new) { |
| fixed = true |
| } |
| if strings.HasPrefix(rename.new, "exp/") { |
| warn(spec.Pos(), "package %q is not part of Go 1", rename.new) |
| } |
| } |
| if !fixed { |
| return false |
| } |
| |
| // Now update the package names used by importers. |
| for _, rename := range go1PackageNameRenames { |
| // These are rare packages, so do the import test before walking. |
| if imports(f, rename.newPath) { |
| walk(f, func(n interface{}) { |
| if sel, ok := n.(*ast.SelectorExpr); ok { |
| if isTopName(sel.X, rename.old) { |
| // We know Sel.X is an Ident. |
| sel.X.(*ast.Ident).Name = rename.new |
| return |
| } |
| } |
| }) |
| } |
| } |
| |
| return fixed |
| } |