mirror of
https://github.com/golang/go
synced 2024-11-17 18:44:44 -07:00
cmd/fix: remove un-used code
Change-Id: Ibbd9da6fd1f3219c9c6103d8f858347ab3a21210 Reviewed-on: https://go-review.googlesource.com/c/go/+/250857 Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
63828096f6
commit
6f561e65b1
@ -7,13 +7,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type fix struct {
|
||||
@ -323,160 +319,12 @@ func declImports(gen *ast.GenDecl, path string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// isPkgDot reports whether t is the expression "pkg.name"
|
||||
// where pkg is an imported identifier.
|
||||
func isPkgDot(t ast.Expr, pkg, name string) bool {
|
||||
sel, ok := t.(*ast.SelectorExpr)
|
||||
return ok && isTopName(sel.X, pkg) && sel.Sel.String() == name
|
||||
}
|
||||
|
||||
// isPtrPkgDot reports whether f is the expression "*pkg.name"
|
||||
// where pkg is an imported identifier.
|
||||
func isPtrPkgDot(t ast.Expr, pkg, name string) bool {
|
||||
ptr, ok := t.(*ast.StarExpr)
|
||||
return ok && isPkgDot(ptr.X, pkg, name)
|
||||
}
|
||||
|
||||
// isTopName reports whether n is a top-level unresolved identifier with the given name.
|
||||
func isTopName(n ast.Expr, name string) bool {
|
||||
id, ok := n.(*ast.Ident)
|
||||
return ok && id.Name == name && id.Obj == nil
|
||||
}
|
||||
|
||||
// isName reports whether n is an identifier with the given name.
|
||||
func isName(n ast.Expr, name string) bool {
|
||||
id, ok := n.(*ast.Ident)
|
||||
return ok && id.String() == name
|
||||
}
|
||||
|
||||
// isCall reports whether t is a call to pkg.name.
|
||||
func isCall(t ast.Expr, pkg, name string) bool {
|
||||
call, ok := t.(*ast.CallExpr)
|
||||
return ok && isPkgDot(call.Fun, pkg, name)
|
||||
}
|
||||
|
||||
// If n is an *ast.Ident, isIdent returns it; otherwise isIdent returns nil.
|
||||
func isIdent(n interface{}) *ast.Ident {
|
||||
id, _ := n.(*ast.Ident)
|
||||
return id
|
||||
}
|
||||
|
||||
// refersTo reports whether n is a reference to the same object as x.
|
||||
func refersTo(n ast.Node, x *ast.Ident) bool {
|
||||
id, ok := n.(*ast.Ident)
|
||||
// The test of id.Name == x.Name handles top-level unresolved
|
||||
// identifiers, which all have Obj == nil.
|
||||
return ok && id.Obj == x.Obj && id.Name == x.Name
|
||||
}
|
||||
|
||||
// isBlank reports whether n is the blank identifier.
|
||||
func isBlank(n ast.Expr) bool {
|
||||
return isName(n, "_")
|
||||
}
|
||||
|
||||
// isEmptyString reports whether n is an empty string literal.
|
||||
func isEmptyString(n ast.Expr) bool {
|
||||
lit, ok := n.(*ast.BasicLit)
|
||||
return ok && lit.Kind == token.STRING && len(lit.Value) == 2
|
||||
}
|
||||
|
||||
func warn(pos token.Pos, msg string, args ...interface{}) {
|
||||
if pos.IsValid() {
|
||||
msg = "%s: " + msg
|
||||
arg1 := []interface{}{fset.Position(pos).String()}
|
||||
args = append(arg1, args...)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
||||
}
|
||||
|
||||
// countUses returns the number of uses of the identifier x in scope.
|
||||
func countUses(x *ast.Ident, scope []ast.Stmt) int {
|
||||
count := 0
|
||||
ff := func(n interface{}) {
|
||||
if n, ok := n.(ast.Node); ok && refersTo(n, x) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
for _, n := range scope {
|
||||
walk(n, ff)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// rewriteUses replaces all uses of the identifier x and !x in scope
|
||||
// with f(x.Pos()) and fnot(x.Pos()).
|
||||
func rewriteUses(x *ast.Ident, f, fnot func(token.Pos) ast.Expr, scope []ast.Stmt) {
|
||||
var lastF ast.Expr
|
||||
ff := func(n interface{}) {
|
||||
ptr, ok := n.(*ast.Expr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
nn := *ptr
|
||||
|
||||
// The child node was just walked and possibly replaced.
|
||||
// If it was replaced and this is a negation, replace with fnot(p).
|
||||
not, ok := nn.(*ast.UnaryExpr)
|
||||
if ok && not.Op == token.NOT && not.X == lastF {
|
||||
*ptr = fnot(nn.Pos())
|
||||
return
|
||||
}
|
||||
if refersTo(nn, x) {
|
||||
lastF = f(nn.Pos())
|
||||
*ptr = lastF
|
||||
}
|
||||
}
|
||||
for _, n := range scope {
|
||||
walk(n, ff)
|
||||
}
|
||||
}
|
||||
|
||||
// assignsTo reports whether any of the code in scope assigns to or takes the address of x.
|
||||
func assignsTo(x *ast.Ident, scope []ast.Stmt) bool {
|
||||
assigned := false
|
||||
ff := func(n interface{}) {
|
||||
if assigned {
|
||||
return
|
||||
}
|
||||
switch n := n.(type) {
|
||||
case *ast.UnaryExpr:
|
||||
// use of &x
|
||||
if n.Op == token.AND && refersTo(n.X, x) {
|
||||
assigned = true
|
||||
return
|
||||
}
|
||||
case *ast.AssignStmt:
|
||||
for _, l := range n.Lhs {
|
||||
if refersTo(l, x) {
|
||||
assigned = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, n := range scope {
|
||||
if assigned {
|
||||
break
|
||||
}
|
||||
walk(n, ff)
|
||||
}
|
||||
return assigned
|
||||
}
|
||||
|
||||
// newPkgDot returns an ast.Expr referring to "pkg.name" at position pos.
|
||||
func newPkgDot(pos token.Pos, pkg, name string) ast.Expr {
|
||||
return &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
NamePos: pos,
|
||||
Name: pkg,
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
NamePos: pos,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// renameTop renames all references to the top-level name old.
|
||||
// It reports whether it makes any changes.
|
||||
func renameTop(f *ast.File, old, new string) bool {
|
||||
@ -707,143 +555,3 @@ func rewriteImport(f *ast.File, oldPath, newPath string) (rewrote bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func usesImport(f *ast.File, path string) (used bool) {
|
||||
spec := importSpec(f, path)
|
||||
if spec == nil {
|
||||
return
|
||||
}
|
||||
|
||||
name := spec.Name.String()
|
||||
switch name {
|
||||
case "<nil>":
|
||||
// If the package name is not explicitly specified,
|
||||
// make an educated guess. This is not guaranteed to be correct.
|
||||
lastSlash := strings.LastIndex(path, "/")
|
||||
if lastSlash == -1 {
|
||||
name = path
|
||||
} else {
|
||||
name = path[lastSlash+1:]
|
||||
}
|
||||
case "_", ".":
|
||||
// Not sure if this import is used - err on the side of caution.
|
||||
return true
|
||||
}
|
||||
|
||||
walk(f, func(n interface{}) {
|
||||
sel, ok := n.(*ast.SelectorExpr)
|
||||
if ok && isTopName(sel.X, name) {
|
||||
used = true
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func expr(s string) ast.Expr {
|
||||
x, err := parser.ParseExpr(s)
|
||||
if err != nil {
|
||||
panic("parsing " + s + ": " + err.Error())
|
||||
}
|
||||
// Remove position information to avoid spurious newlines.
|
||||
killPos(reflect.ValueOf(x))
|
||||
return x
|
||||
}
|
||||
|
||||
var posType = reflect.TypeOf(token.Pos(0))
|
||||
|
||||
func killPos(v reflect.Value) {
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
if !v.IsNil() {
|
||||
killPos(v.Elem())
|
||||
}
|
||||
case reflect.Slice:
|
||||
n := v.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
killPos(v.Index(i))
|
||||
}
|
||||
case reflect.Struct:
|
||||
n := v.NumField()
|
||||
for i := 0; i < n; i++ {
|
||||
f := v.Field(i)
|
||||
if f.Type() == posType {
|
||||
f.SetInt(0)
|
||||
continue
|
||||
}
|
||||
killPos(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A Rename describes a single renaming.
|
||||
type rename struct {
|
||||
OldImport string // only apply rename if this import is present
|
||||
NewImport string // add this import during rewrite
|
||||
Old string // old name: p.T or *p.T
|
||||
New string // new name: p.T or *p.T
|
||||
}
|
||||
|
||||
func renameFix(tab []rename) func(*ast.File) bool {
|
||||
return func(f *ast.File) bool {
|
||||
return renameFixTab(f, tab)
|
||||
}
|
||||
}
|
||||
|
||||
func parseName(s string) (ptr bool, pkg, nam string) {
|
||||
i := strings.Index(s, ".")
|
||||
if i < 0 {
|
||||
panic("parseName: invalid name " + s)
|
||||
}
|
||||
if strings.HasPrefix(s, "*") {
|
||||
ptr = true
|
||||
s = s[1:]
|
||||
i--
|
||||
}
|
||||
pkg = s[:i]
|
||||
nam = s[i+1:]
|
||||
return
|
||||
}
|
||||
|
||||
func renameFixTab(f *ast.File, tab []rename) bool {
|
||||
fixed := false
|
||||
added := map[string]bool{}
|
||||
check := map[string]bool{}
|
||||
for _, t := range tab {
|
||||
if !imports(f, t.OldImport) {
|
||||
continue
|
||||
}
|
||||
optr, opkg, onam := parseName(t.Old)
|
||||
walk(f, func(n interface{}) {
|
||||
np, ok := n.(*ast.Expr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
x := *np
|
||||
if optr {
|
||||
p, ok := x.(*ast.StarExpr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
x = p.X
|
||||
}
|
||||
if !isPkgDot(x, opkg, onam) {
|
||||
return
|
||||
}
|
||||
if t.NewImport != "" && !added[t.NewImport] {
|
||||
addImport(f, t.NewImport)
|
||||
added[t.NewImport] = true
|
||||
}
|
||||
*np = expr(t.New)
|
||||
check[t.OldImport] = true
|
||||
fixed = true
|
||||
})
|
||||
}
|
||||
|
||||
for ipath := range check {
|
||||
if !usesImport(f, ipath) {
|
||||
deleteImport(f, ipath)
|
||||
}
|
||||
}
|
||||
return fixed
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user