1
0
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:
Cuong Manh Le 2020-08-26 23:18:41 +07:00 committed by Bryan C. Mills
parent 63828096f6
commit 6f561e65b1

View File

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