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