Home | History | Annotate | Download | only in fix
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package main
      6 
      7 import (
      8 	"fmt"
      9 	"go/ast"
     10 	"go/parser"
     11 	"go/token"
     12 	"os"
     13 	"path"
     14 	"reflect"
     15 	"strconv"
     16 	"strings"
     17 )
     18 
     19 type fix struct {
     20 	name     string
     21 	date     string // date that fix was introduced, in YYYY-MM-DD format
     22 	f        func(*ast.File) bool
     23 	desc     string
     24 	disabled bool // whether this fix should be disabled by default
     25 }
     26 
     27 // main runs sort.Sort(byName(fixes)) before printing list of fixes.
     28 type byName []fix
     29 
     30 func (f byName) Len() int           { return len(f) }
     31 func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
     32 func (f byName) Less(i, j int) bool { return f[i].name < f[j].name }
     33 
     34 // main runs sort.Sort(byDate(fixes)) before applying fixes.
     35 type byDate []fix
     36 
     37 func (f byDate) Len() int           { return len(f) }
     38 func (f byDate) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
     39 func (f byDate) Less(i, j int) bool { return f[i].date < f[j].date }
     40 
     41 var fixes []fix
     42 
     43 func register(f fix) {
     44 	fixes = append(fixes, f)
     45 }
     46 
     47 // walk traverses the AST x, calling visit(y) for each node y in the tree but
     48 // also with a pointer to each ast.Expr, ast.Stmt, and *ast.BlockStmt,
     49 // in a bottom-up traversal.
     50 func walk(x interface{}, visit func(interface{})) {
     51 	walkBeforeAfter(x, nop, visit)
     52 }
     53 
     54 func nop(interface{}) {}
     55 
     56 // walkBeforeAfter is like walk but calls before(x) before traversing
     57 // x's children and after(x) afterward.
     58 func walkBeforeAfter(x interface{}, before, after func(interface{})) {
     59 	before(x)
     60 
     61 	switch n := x.(type) {
     62 	default:
     63 		panic(fmt.Errorf("unexpected type %T in walkBeforeAfter", x))
     64 
     65 	case nil:
     66 
     67 	// pointers to interfaces
     68 	case *ast.Decl:
     69 		walkBeforeAfter(*n, before, after)
     70 	case *ast.Expr:
     71 		walkBeforeAfter(*n, before, after)
     72 	case *ast.Spec:
     73 		walkBeforeAfter(*n, before, after)
     74 	case *ast.Stmt:
     75 		walkBeforeAfter(*n, before, after)
     76 
     77 	// pointers to struct pointers
     78 	case **ast.BlockStmt:
     79 		walkBeforeAfter(*n, before, after)
     80 	case **ast.CallExpr:
     81 		walkBeforeAfter(*n, before, after)
     82 	case **ast.FieldList:
     83 		walkBeforeAfter(*n, before, after)
     84 	case **ast.FuncType:
     85 		walkBeforeAfter(*n, before, after)
     86 	case **ast.Ident:
     87 		walkBeforeAfter(*n, before, after)
     88 	case **ast.BasicLit:
     89 		walkBeforeAfter(*n, before, after)
     90 
     91 	// pointers to slices
     92 	case *[]ast.Decl:
     93 		walkBeforeAfter(*n, before, after)
     94 	case *[]ast.Expr:
     95 		walkBeforeAfter(*n, before, after)
     96 	case *[]*ast.File:
     97 		walkBeforeAfter(*n, before, after)
     98 	case *[]*ast.Ident:
     99 		walkBeforeAfter(*n, before, after)
    100 	case *[]ast.Spec:
    101 		walkBeforeAfter(*n, before, after)
    102 	case *[]ast.Stmt:
    103 		walkBeforeAfter(*n, before, after)
    104 
    105 	// These are ordered and grouped to match ../../go/ast/ast.go
    106 	case *ast.Field:
    107 		walkBeforeAfter(&n.Names, before, after)
    108 		walkBeforeAfter(&n.Type, before, after)
    109 		walkBeforeAfter(&n.Tag, before, after)
    110 	case *ast.FieldList:
    111 		for _, field := range n.List {
    112 			walkBeforeAfter(field, before, after)
    113 		}
    114 	case *ast.BadExpr:
    115 	case *ast.Ident:
    116 	case *ast.Ellipsis:
    117 		walkBeforeAfter(&n.Elt, before, after)
    118 	case *ast.BasicLit:
    119 	case *ast.FuncLit:
    120 		walkBeforeAfter(&n.Type, before, after)
    121 		walkBeforeAfter(&n.Body, before, after)
    122 	case *ast.CompositeLit:
    123 		walkBeforeAfter(&n.Type, before, after)
    124 		walkBeforeAfter(&n.Elts, before, after)
    125 	case *ast.ParenExpr:
    126 		walkBeforeAfter(&n.X, before, after)
    127 	case *ast.SelectorExpr:
    128 		walkBeforeAfter(&n.X, before, after)
    129 	case *ast.IndexExpr:
    130 		walkBeforeAfter(&n.X, before, after)
    131 		walkBeforeAfter(&n.Index, before, after)
    132 	case *ast.SliceExpr:
    133 		walkBeforeAfter(&n.X, before, after)
    134 		if n.Low != nil {
    135 			walkBeforeAfter(&n.Low, before, after)
    136 		}
    137 		if n.High != nil {
    138 			walkBeforeAfter(&n.High, before, after)
    139 		}
    140 	case *ast.TypeAssertExpr:
    141 		walkBeforeAfter(&n.X, before, after)
    142 		walkBeforeAfter(&n.Type, before, after)
    143 	case *ast.CallExpr:
    144 		walkBeforeAfter(&n.Fun, before, after)
    145 		walkBeforeAfter(&n.Args, before, after)
    146 	case *ast.StarExpr:
    147 		walkBeforeAfter(&n.X, before, after)
    148 	case *ast.UnaryExpr:
    149 		walkBeforeAfter(&n.X, before, after)
    150 	case *ast.BinaryExpr:
    151 		walkBeforeAfter(&n.X, before, after)
    152 		walkBeforeAfter(&n.Y, before, after)
    153 	case *ast.KeyValueExpr:
    154 		walkBeforeAfter(&n.Key, before, after)
    155 		walkBeforeAfter(&n.Value, before, after)
    156 
    157 	case *ast.ArrayType:
    158 		walkBeforeAfter(&n.Len, before, after)
    159 		walkBeforeAfter(&n.Elt, before, after)
    160 	case *ast.StructType:
    161 		walkBeforeAfter(&n.Fields, before, after)
    162 	case *ast.FuncType:
    163 		walkBeforeAfter(&n.Params, before, after)
    164 		if n.Results != nil {
    165 			walkBeforeAfter(&n.Results, before, after)
    166 		}
    167 	case *ast.InterfaceType:
    168 		walkBeforeAfter(&n.Methods, before, after)
    169 	case *ast.MapType:
    170 		walkBeforeAfter(&n.Key, before, after)
    171 		walkBeforeAfter(&n.Value, before, after)
    172 	case *ast.ChanType:
    173 		walkBeforeAfter(&n.Value, before, after)
    174 
    175 	case *ast.BadStmt:
    176 	case *ast.DeclStmt:
    177 		walkBeforeAfter(&n.Decl, before, after)
    178 	case *ast.EmptyStmt:
    179 	case *ast.LabeledStmt:
    180 		walkBeforeAfter(&n.Stmt, before, after)
    181 	case *ast.ExprStmt:
    182 		walkBeforeAfter(&n.X, before, after)
    183 	case *ast.SendStmt:
    184 		walkBeforeAfter(&n.Chan, before, after)
    185 		walkBeforeAfter(&n.Value, before, after)
    186 	case *ast.IncDecStmt:
    187 		walkBeforeAfter(&n.X, before, after)
    188 	case *ast.AssignStmt:
    189 		walkBeforeAfter(&n.Lhs, before, after)
    190 		walkBeforeAfter(&n.Rhs, before, after)
    191 	case *ast.GoStmt:
    192 		walkBeforeAfter(&n.Call, before, after)
    193 	case *ast.DeferStmt:
    194 		walkBeforeAfter(&n.Call, before, after)
    195 	case *ast.ReturnStmt:
    196 		walkBeforeAfter(&n.Results, before, after)
    197 	case *ast.BranchStmt:
    198 	case *ast.BlockStmt:
    199 		walkBeforeAfter(&n.List, before, after)
    200 	case *ast.IfStmt:
    201 		walkBeforeAfter(&n.Init, before, after)
    202 		walkBeforeAfter(&n.Cond, before, after)
    203 		walkBeforeAfter(&n.Body, before, after)
    204 		walkBeforeAfter(&n.Else, before, after)
    205 	case *ast.CaseClause:
    206 		walkBeforeAfter(&n.List, before, after)
    207 		walkBeforeAfter(&n.Body, before, after)
    208 	case *ast.SwitchStmt:
    209 		walkBeforeAfter(&n.Init, before, after)
    210 		walkBeforeAfter(&n.Tag, before, after)
    211 		walkBeforeAfter(&n.Body, before, after)
    212 	case *ast.TypeSwitchStmt:
    213 		walkBeforeAfter(&n.Init, before, after)
    214 		walkBeforeAfter(&n.Assign, before, after)
    215 		walkBeforeAfter(&n.Body, before, after)
    216 	case *ast.CommClause:
    217 		walkBeforeAfter(&n.Comm, before, after)
    218 		walkBeforeAfter(&n.Body, before, after)
    219 	case *ast.SelectStmt:
    220 		walkBeforeAfter(&n.Body, before, after)
    221 	case *ast.ForStmt:
    222 		walkBeforeAfter(&n.Init, before, after)
    223 		walkBeforeAfter(&n.Cond, before, after)
    224 		walkBeforeAfter(&n.Post, before, after)
    225 		walkBeforeAfter(&n.Body, before, after)
    226 	case *ast.RangeStmt:
    227 		walkBeforeAfter(&n.Key, before, after)
    228 		walkBeforeAfter(&n.Value, before, after)
    229 		walkBeforeAfter(&n.X, before, after)
    230 		walkBeforeAfter(&n.Body, before, after)
    231 
    232 	case *ast.ImportSpec:
    233 	case *ast.ValueSpec:
    234 		walkBeforeAfter(&n.Type, before, after)
    235 		walkBeforeAfter(&n.Values, before, after)
    236 		walkBeforeAfter(&n.Names, before, after)
    237 	case *ast.TypeSpec:
    238 		walkBeforeAfter(&n.Type, before, after)
    239 
    240 	case *ast.BadDecl:
    241 	case *ast.GenDecl:
    242 		walkBeforeAfter(&n.Specs, before, after)
    243 	case *ast.FuncDecl:
    244 		if n.Recv != nil {
    245 			walkBeforeAfter(&n.Recv, before, after)
    246 		}
    247 		walkBeforeAfter(&n.Type, before, after)
    248 		if n.Body != nil {
    249 			walkBeforeAfter(&n.Body, before, after)
    250 		}
    251 
    252 	case *ast.File:
    253 		walkBeforeAfter(&n.Decls, before, after)
    254 
    255 	case *ast.Package:
    256 		walkBeforeAfter(&n.Files, before, after)
    257 
    258 	case []*ast.File:
    259 		for i := range n {
    260 			walkBeforeAfter(&n[i], before, after)
    261 		}
    262 	case []ast.Decl:
    263 		for i := range n {
    264 			walkBeforeAfter(&n[i], before, after)
    265 		}
    266 	case []ast.Expr:
    267 		for i := range n {
    268 			walkBeforeAfter(&n[i], before, after)
    269 		}
    270 	case []*ast.Ident:
    271 		for i := range n {
    272 			walkBeforeAfter(&n[i], before, after)
    273 		}
    274 	case []ast.Stmt:
    275 		for i := range n {
    276 			walkBeforeAfter(&n[i], before, after)
    277 		}
    278 	case []ast.Spec:
    279 		for i := range n {
    280 			walkBeforeAfter(&n[i], before, after)
    281 		}
    282 	}
    283 	after(x)
    284 }
    285 
    286 // imports reports whether f imports path.
    287 func imports(f *ast.File, path string) bool {
    288 	return importSpec(f, path) != nil
    289 }
    290 
    291 // importSpec returns the import spec if f imports path,
    292 // or nil otherwise.
    293 func importSpec(f *ast.File, path string) *ast.ImportSpec {
    294 	for _, s := range f.Imports {
    295 		if importPath(s) == path {
    296 			return s
    297 		}
    298 	}
    299 	return nil
    300 }
    301 
    302 // importPath returns the unquoted import path of s,
    303 // or "" if the path is not properly quoted.
    304 func importPath(s *ast.ImportSpec) string {
    305 	t, err := strconv.Unquote(s.Path.Value)
    306 	if err == nil {
    307 		return t
    308 	}
    309 	return ""
    310 }
    311 
    312 // declImports reports whether gen contains an import of path.
    313 func declImports(gen *ast.GenDecl, path string) bool {
    314 	if gen.Tok != token.IMPORT {
    315 		return false
    316 	}
    317 	for _, spec := range gen.Specs {
    318 		impspec := spec.(*ast.ImportSpec)
    319 		if importPath(impspec) == path {
    320 			return true
    321 		}
    322 	}
    323 	return false
    324 }
    325 
    326 // isPkgDot reports whether t is the expression "pkg.name"
    327 // where pkg is an imported identifier.
    328 func isPkgDot(t ast.Expr, pkg, name string) bool {
    329 	sel, ok := t.(*ast.SelectorExpr)
    330 	return ok && isTopName(sel.X, pkg) && sel.Sel.String() == name
    331 }
    332 
    333 // isPtrPkgDot reports whether f is the expression "*pkg.name"
    334 // where pkg is an imported identifier.
    335 func isPtrPkgDot(t ast.Expr, pkg, name string) bool {
    336 	ptr, ok := t.(*ast.StarExpr)
    337 	return ok && isPkgDot(ptr.X, pkg, name)
    338 }
    339 
    340 // isTopName reports whether n is a top-level unresolved identifier with the given name.
    341 func isTopName(n ast.Expr, name string) bool {
    342 	id, ok := n.(*ast.Ident)
    343 	return ok && id.Name == name && id.Obj == nil
    344 }
    345 
    346 // isName reports whether n is an identifier with the given name.
    347 func isName(n ast.Expr, name string) bool {
    348 	id, ok := n.(*ast.Ident)
    349 	return ok && id.String() == name
    350 }
    351 
    352 // isCall reports whether t is a call to pkg.name.
    353 func isCall(t ast.Expr, pkg, name string) bool {
    354 	call, ok := t.(*ast.CallExpr)
    355 	return ok && isPkgDot(call.Fun, pkg, name)
    356 }
    357 
    358 // If n is an *ast.Ident, isIdent returns it; otherwise isIdent returns nil.
    359 func isIdent(n interface{}) *ast.Ident {
    360 	id, _ := n.(*ast.Ident)
    361 	return id
    362 }
    363 
    364 // refersTo reports whether n is a reference to the same object as x.
    365 func refersTo(n ast.Node, x *ast.Ident) bool {
    366 	id, ok := n.(*ast.Ident)
    367 	// The test of id.Name == x.Name handles top-level unresolved
    368 	// identifiers, which all have Obj == nil.
    369 	return ok && id.Obj == x.Obj && id.Name == x.Name
    370 }
    371 
    372 // isBlank reports whether n is the blank identifier.
    373 func isBlank(n ast.Expr) bool {
    374 	return isName(n, "_")
    375 }
    376 
    377 // isEmptyString reports whether n is an empty string literal.
    378 func isEmptyString(n ast.Expr) bool {
    379 	lit, ok := n.(*ast.BasicLit)
    380 	return ok && lit.Kind == token.STRING && len(lit.Value) == 2
    381 }
    382 
    383 func warn(pos token.Pos, msg string, args ...interface{}) {
    384 	if pos.IsValid() {
    385 		msg = "%s: " + msg
    386 		arg1 := []interface{}{fset.Position(pos).String()}
    387 		args = append(arg1, args...)
    388 	}
    389 	fmt.Fprintf(os.Stderr, msg+"\n", args...)
    390 }
    391 
    392 // countUses returns the number of uses of the identifier x in scope.
    393 func countUses(x *ast.Ident, scope []ast.Stmt) int {
    394 	count := 0
    395 	ff := func(n interface{}) {
    396 		if n, ok := n.(ast.Node); ok && refersTo(n, x) {
    397 			count++
    398 		}
    399 	}
    400 	for _, n := range scope {
    401 		walk(n, ff)
    402 	}
    403 	return count
    404 }
    405 
    406 // rewriteUses replaces all uses of the identifier x and !x in scope
    407 // with f(x.Pos()) and fnot(x.Pos()).
    408 func rewriteUses(x *ast.Ident, f, fnot func(token.Pos) ast.Expr, scope []ast.Stmt) {
    409 	var lastF ast.Expr
    410 	ff := func(n interface{}) {
    411 		ptr, ok := n.(*ast.Expr)
    412 		if !ok {
    413 			return
    414 		}
    415 		nn := *ptr
    416 
    417 		// The child node was just walked and possibly replaced.
    418 		// If it was replaced and this is a negation, replace with fnot(p).
    419 		not, ok := nn.(*ast.UnaryExpr)
    420 		if ok && not.Op == token.NOT && not.X == lastF {
    421 			*ptr = fnot(nn.Pos())
    422 			return
    423 		}
    424 		if refersTo(nn, x) {
    425 			lastF = f(nn.Pos())
    426 			*ptr = lastF
    427 		}
    428 	}
    429 	for _, n := range scope {
    430 		walk(n, ff)
    431 	}
    432 }
    433 
    434 // assignsTo reports whether any of the code in scope assigns to or takes the address of x.
    435 func assignsTo(x *ast.Ident, scope []ast.Stmt) bool {
    436 	assigned := false
    437 	ff := func(n interface{}) {
    438 		if assigned {
    439 			return
    440 		}
    441 		switch n := n.(type) {
    442 		case *ast.UnaryExpr:
    443 			// use of &x
    444 			if n.Op == token.AND && refersTo(n.X, x) {
    445 				assigned = true
    446 				return
    447 			}
    448 		case *ast.AssignStmt:
    449 			for _, l := range n.Lhs {
    450 				if refersTo(l, x) {
    451 					assigned = true
    452 					return
    453 				}
    454 			}
    455 		}
    456 	}
    457 	for _, n := range scope {
    458 		if assigned {
    459 			break
    460 		}
    461 		walk(n, ff)
    462 	}
    463 	return assigned
    464 }
    465 
    466 // newPkgDot returns an ast.Expr referring to "pkg.name" at position pos.
    467 func newPkgDot(pos token.Pos, pkg, name string) ast.Expr {
    468 	return &ast.SelectorExpr{
    469 		X: &ast.Ident{
    470 			NamePos: pos,
    471 			Name:    pkg,
    472 		},
    473 		Sel: &ast.Ident{
    474 			NamePos: pos,
    475 			Name:    name,
    476 		},
    477 	}
    478 }
    479 
    480 // renameTop renames all references to the top-level name old.
    481 // It returns true if it makes any changes.
    482 func renameTop(f *ast.File, old, new string) bool {
    483 	var fixed bool
    484 
    485 	// Rename any conflicting imports
    486 	// (assuming package name is last element of path).
    487 	for _, s := range f.Imports {
    488 		if s.Name != nil {
    489 			if s.Name.Name == old {
    490 				s.Name.Name = new
    491 				fixed = true
    492 			}
    493 		} else {
    494 			_, thisName := path.Split(importPath(s))
    495 			if thisName == old {
    496 				s.Name = ast.NewIdent(new)
    497 				fixed = true
    498 			}
    499 		}
    500 	}
    501 
    502 	// Rename any top-level declarations.
    503 	for _, d := range f.Decls {
    504 		switch d := d.(type) {
    505 		case *ast.FuncDecl:
    506 			if d.Recv == nil && d.Name.Name == old {
    507 				d.Name.Name = new
    508 				d.Name.Obj.Name = new
    509 				fixed = true
    510 			}
    511 		case *ast.GenDecl:
    512 			for _, s := range d.Specs {
    513 				switch s := s.(type) {
    514 				case *ast.TypeSpec:
    515 					if s.Name.Name == old {
    516 						s.Name.Name = new
    517 						s.Name.Obj.Name = new
    518 						fixed = true
    519 					}
    520 				case *ast.ValueSpec:
    521 					for _, n := range s.Names {
    522 						if n.Name == old {
    523 							n.Name = new
    524 							n.Obj.Name = new
    525 							fixed = true
    526 						}
    527 					}
    528 				}
    529 			}
    530 		}
    531 	}
    532 
    533 	// Rename top-level old to new, both unresolved names
    534 	// (probably defined in another file) and names that resolve
    535 	// to a declaration we renamed.
    536 	walk(f, func(n interface{}) {
    537 		id, ok := n.(*ast.Ident)
    538 		if ok && isTopName(id, old) {
    539 			id.Name = new
    540 			fixed = true
    541 		}
    542 		if ok && id.Obj != nil && id.Name == old && id.Obj.Name == new {
    543 			id.Name = id.Obj.Name
    544 			fixed = true
    545 		}
    546 	})
    547 
    548 	return fixed
    549 }
    550 
    551 // matchLen returns the length of the longest prefix shared by x and y.
    552 func matchLen(x, y string) int {
    553 	i := 0
    554 	for i < len(x) && i < len(y) && x[i] == y[i] {
    555 		i++
    556 	}
    557 	return i
    558 }
    559 
    560 // addImport adds the import path to the file f, if absent.
    561 func addImport(f *ast.File, ipath string) (added bool) {
    562 	if imports(f, ipath) {
    563 		return false
    564 	}
    565 
    566 	// Determine name of import.
    567 	// Assume added imports follow convention of using last element.
    568 	_, name := path.Split(ipath)
    569 
    570 	// Rename any conflicting top-level references from name to name_.
    571 	renameTop(f, name, name+"_")
    572 
    573 	newImport := &ast.ImportSpec{
    574 		Path: &ast.BasicLit{
    575 			Kind:  token.STRING,
    576 			Value: strconv.Quote(ipath),
    577 		},
    578 	}
    579 
    580 	// Find an import decl to add to.
    581 	var (
    582 		bestMatch  = -1
    583 		lastImport = -1
    584 		impDecl    *ast.GenDecl
    585 		impIndex   = -1
    586 	)
    587 	for i, decl := range f.Decls {
    588 		gen, ok := decl.(*ast.GenDecl)
    589 		if ok && gen.Tok == token.IMPORT {
    590 			lastImport = i
    591 			// Do not add to import "C", to avoid disrupting the
    592 			// association with its doc comment, breaking cgo.
    593 			if declImports(gen, "C") {
    594 				continue
    595 			}
    596 
    597 			// Compute longest shared prefix with imports in this block.
    598 			for j, spec := range gen.Specs {
    599 				impspec := spec.(*ast.ImportSpec)
    600 				n := matchLen(importPath(impspec), ipath)
    601 				if n > bestMatch {
    602 					bestMatch = n
    603 					impDecl = gen
    604 					impIndex = j
    605 				}
    606 			}
    607 		}
    608 	}
    609 
    610 	// If no import decl found, add one after the last import.
    611 	if impDecl == nil {
    612 		impDecl = &ast.GenDecl{
    613 			Tok: token.IMPORT,
    614 		}
    615 		f.Decls = append(f.Decls, nil)
    616 		copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:])
    617 		f.Decls[lastImport+1] = impDecl
    618 	}
    619 
    620 	// Ensure the import decl has parentheses, if needed.
    621 	if len(impDecl.Specs) > 0 && !impDecl.Lparen.IsValid() {
    622 		impDecl.Lparen = impDecl.Pos()
    623 	}
    624 
    625 	insertAt := impIndex + 1
    626 	if insertAt == 0 {
    627 		insertAt = len(impDecl.Specs)
    628 	}
    629 	impDecl.Specs = append(impDecl.Specs, nil)
    630 	copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:])
    631 	impDecl.Specs[insertAt] = newImport
    632 	if insertAt > 0 {
    633 		// Assign same position as the previous import,
    634 		// so that the sorter sees it as being in the same block.
    635 		prev := impDecl.Specs[insertAt-1]
    636 		newImport.Path.ValuePos = prev.Pos()
    637 		newImport.EndPos = prev.Pos()
    638 	}
    639 
    640 	f.Imports = append(f.Imports, newImport)
    641 	return true
    642 }
    643 
    644 // deleteImport deletes the import path from the file f, if present.
    645 func deleteImport(f *ast.File, path string) (deleted bool) {
    646 	oldImport := importSpec(f, path)
    647 
    648 	// Find the import node that imports path, if any.
    649 	for i, decl := range f.Decls {
    650 		gen, ok := decl.(*ast.GenDecl)
    651 		if !ok || gen.Tok != token.IMPORT {
    652 			continue
    653 		}
    654 		for j, spec := range gen.Specs {
    655 			impspec := spec.(*ast.ImportSpec)
    656 			if oldImport != impspec {
    657 				continue
    658 			}
    659 
    660 			// We found an import spec that imports path.
    661 			// Delete it.
    662 			deleted = true
    663 			copy(gen.Specs[j:], gen.Specs[j+1:])
    664 			gen.Specs = gen.Specs[:len(gen.Specs)-1]
    665 
    666 			// If this was the last import spec in this decl,
    667 			// delete the decl, too.
    668 			if len(gen.Specs) == 0 {
    669 				copy(f.Decls[i:], f.Decls[i+1:])
    670 				f.Decls = f.Decls[:len(f.Decls)-1]
    671 			} else if len(gen.Specs) == 1 {
    672 				gen.Lparen = token.NoPos // drop parens
    673 			}
    674 			if j > 0 {
    675 				// We deleted an entry but now there will be
    676 				// a blank line-sized hole where the import was.
    677 				// Close the hole by making the previous
    678 				// import appear to "end" where this one did.
    679 				gen.Specs[j-1].(*ast.ImportSpec).EndPos = impspec.End()
    680 			}
    681 			break
    682 		}
    683 	}
    684 
    685 	// Delete it from f.Imports.
    686 	for i, imp := range f.Imports {
    687 		if imp == oldImport {
    688 			copy(f.Imports[i:], f.Imports[i+1:])
    689 			f.Imports = f.Imports[:len(f.Imports)-1]
    690 			break
    691 		}
    692 	}
    693 
    694 	return
    695 }
    696 
    697 // rewriteImport rewrites any import of path oldPath to path newPath.
    698 func rewriteImport(f *ast.File, oldPath, newPath string) (rewrote bool) {
    699 	for _, imp := range f.Imports {
    700 		if importPath(imp) == oldPath {
    701 			rewrote = true
    702 			// record old End, because the default is to compute
    703 			// it using the length of imp.Path.Value.
    704 			imp.EndPos = imp.End()
    705 			imp.Path.Value = strconv.Quote(newPath)
    706 		}
    707 	}
    708 	return
    709 }
    710 
    711 func usesImport(f *ast.File, path string) (used bool) {
    712 	spec := importSpec(f, path)
    713 	if spec == nil {
    714 		return
    715 	}
    716 
    717 	name := spec.Name.String()
    718 	switch name {
    719 	case "<nil>":
    720 		// If the package name is not explicitly specified,
    721 		// make an educated guess. This is not guaranteed to be correct.
    722 		lastSlash := strings.LastIndex(path, "/")
    723 		if lastSlash == -1 {
    724 			name = path
    725 		} else {
    726 			name = path[lastSlash+1:]
    727 		}
    728 	case "_", ".":
    729 		// Not sure if this import is used - err on the side of caution.
    730 		return true
    731 	}
    732 
    733 	walk(f, func(n interface{}) {
    734 		sel, ok := n.(*ast.SelectorExpr)
    735 		if ok && isTopName(sel.X, name) {
    736 			used = true
    737 		}
    738 	})
    739 
    740 	return
    741 }
    742 
    743 func expr(s string) ast.Expr {
    744 	x, err := parser.ParseExpr(s)
    745 	if err != nil {
    746 		panic("parsing " + s + ": " + err.Error())
    747 	}
    748 	// Remove position information to avoid spurious newlines.
    749 	killPos(reflect.ValueOf(x))
    750 	return x
    751 }
    752 
    753 var posType = reflect.TypeOf(token.Pos(0))
    754 
    755 func killPos(v reflect.Value) {
    756 	switch v.Kind() {
    757 	case reflect.Ptr, reflect.Interface:
    758 		if !v.IsNil() {
    759 			killPos(v.Elem())
    760 		}
    761 	case reflect.Slice:
    762 		n := v.Len()
    763 		for i := 0; i < n; i++ {
    764 			killPos(v.Index(i))
    765 		}
    766 	case reflect.Struct:
    767 		n := v.NumField()
    768 		for i := 0; i < n; i++ {
    769 			f := v.Field(i)
    770 			if f.Type() == posType {
    771 				f.SetInt(0)
    772 				continue
    773 			}
    774 			killPos(f)
    775 		}
    776 	}
    777 }
    778 
    779 // A Rename describes a single renaming.
    780 type rename struct {
    781 	OldImport string // only apply rename if this import is present
    782 	NewImport string // add this import during rewrite
    783 	Old       string // old name: p.T or *p.T
    784 	New       string // new name: p.T or *p.T
    785 }
    786 
    787 func renameFix(tab []rename) func(*ast.File) bool {
    788 	return func(f *ast.File) bool {
    789 		return renameFixTab(f, tab)
    790 	}
    791 }
    792 
    793 func parseName(s string) (ptr bool, pkg, nam string) {
    794 	i := strings.Index(s, ".")
    795 	if i < 0 {
    796 		panic("parseName: invalid name " + s)
    797 	}
    798 	if strings.HasPrefix(s, "*") {
    799 		ptr = true
    800 		s = s[1:]
    801 		i--
    802 	}
    803 	pkg = s[:i]
    804 	nam = s[i+1:]
    805 	return
    806 }
    807 
    808 func renameFixTab(f *ast.File, tab []rename) bool {
    809 	fixed := false
    810 	added := map[string]bool{}
    811 	check := map[string]bool{}
    812 	for _, t := range tab {
    813 		if !imports(f, t.OldImport) {
    814 			continue
    815 		}
    816 		optr, opkg, onam := parseName(t.Old)
    817 		walk(f, func(n interface{}) {
    818 			np, ok := n.(*ast.Expr)
    819 			if !ok {
    820 				return
    821 			}
    822 			x := *np
    823 			if optr {
    824 				p, ok := x.(*ast.StarExpr)
    825 				if !ok {
    826 					return
    827 				}
    828 				x = p.X
    829 			}
    830 			if !isPkgDot(x, opkg, onam) {
    831 				return
    832 			}
    833 			if t.NewImport != "" && !added[t.NewImport] {
    834 				addImport(f, t.NewImport)
    835 				added[t.NewImport] = true
    836 			}
    837 			*np = expr(t.New)
    838 			check[t.OldImport] = true
    839 			fixed = true
    840 		})
    841 	}
    842 
    843 	for ipath := range check {
    844 		if !usesImport(f, ipath) {
    845 			deleteImport(f, ipath)
    846 		}
    847 	}
    848 	return fixed
    849 }
    850