Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / source / rename_check.go
1 // Copyright 2019 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 // Taken from golang.org/x/tools/refactor/rename.
6
7 package source
8
9 import (
10         "fmt"
11         "go/ast"
12         "go/token"
13         "go/types"
14         "reflect"
15         "strconv"
16         "strings"
17         "unicode"
18
19         "golang.org/x/tools/go/ast/astutil"
20         "golang.org/x/tools/refactor/satisfy"
21 )
22
23 // errorf reports an error (e.g. conflict) and prevents file modification.
24 func (r *renamer) errorf(pos token.Pos, format string, args ...interface{}) {
25         r.hadConflicts = true
26         r.errors += fmt.Sprintf(format, args...)
27 }
28
29 // check performs safety checks of the renaming of the 'from' object to r.to.
30 func (r *renamer) check(from types.Object) {
31         if r.objsToUpdate[from] {
32                 return
33         }
34         r.objsToUpdate[from] = true
35
36         // NB: order of conditions is important.
37         if from_, ok := from.(*types.PkgName); ok {
38                 r.checkInFileBlock(from_)
39         } else if from_, ok := from.(*types.Label); ok {
40                 r.checkLabel(from_)
41         } else if isPackageLevel(from) {
42                 r.checkInPackageBlock(from)
43         } else if v, ok := from.(*types.Var); ok && v.IsField() {
44                 r.checkStructField(v)
45         } else if f, ok := from.(*types.Func); ok && recv(f) != nil {
46                 r.checkMethod(f)
47         } else if isLocal(from) {
48                 r.checkInLocalScope(from)
49         } else {
50                 r.errorf(from.Pos(), "unexpected %s object %q (please report a bug)\n",
51                         objectKind(from), from)
52         }
53 }
54
55 // checkInFileBlock performs safety checks for renames of objects in the file block,
56 // i.e. imported package names.
57 func (r *renamer) checkInFileBlock(from *types.PkgName) {
58         // Check import name is not "init".
59         if r.to == "init" {
60                 r.errorf(from.Pos(), "%q is not a valid imported package name", r.to)
61         }
62
63         // Check for conflicts between file and package block.
64         if prev := from.Pkg().Scope().Lookup(r.to); prev != nil {
65                 r.errorf(from.Pos(), "renaming this %s %q to %q would conflict",
66                         objectKind(from), from.Name(), r.to)
67                 r.errorf(prev.Pos(), "\twith this package member %s",
68                         objectKind(prev))
69                 return // since checkInPackageBlock would report redundant errors
70         }
71
72         // Check for conflicts in lexical scope.
73         r.checkInLexicalScope(from, r.packages[from.Pkg()])
74 }
75
76 // checkInPackageBlock performs safety checks for renames of
77 // func/var/const/type objects in the package block.
78 func (r *renamer) checkInPackageBlock(from types.Object) {
79         // Check that there are no references to the name from another
80         // package if the renaming would make it unexported.
81         if ast.IsExported(from.Name()) && !ast.IsExported(r.to) {
82                 for typ, pkg := range r.packages {
83                         if typ == from.Pkg() {
84                                 continue
85                         }
86                         if id := someUse(pkg.GetTypesInfo(), from); id != nil &&
87                                 !r.checkExport(id, typ, from) {
88                                 break
89                         }
90                 }
91         }
92
93         pkg := r.packages[from.Pkg()]
94         if pkg == nil {
95                 return
96         }
97
98         // Check that in the package block, "init" is a function, and never referenced.
99         if r.to == "init" {
100                 kind := objectKind(from)
101                 if kind == "func" {
102                         // Reject if intra-package references to it exist.
103                         for id, obj := range pkg.GetTypesInfo().Uses {
104                                 if obj == from {
105                                         r.errorf(from.Pos(),
106                                                 "renaming this func %q to %q would make it a package initializer",
107                                                 from.Name(), r.to)
108                                         r.errorf(id.Pos(), "\tbut references to it exist")
109                                         break
110                                 }
111                         }
112                 } else {
113                         r.errorf(from.Pos(), "you cannot have a %s at package level named %q",
114                                 kind, r.to)
115                 }
116         }
117
118         // Check for conflicts between package block and all file blocks.
119         for _, f := range pkg.GetSyntax() {
120                 fileScope := pkg.GetTypesInfo().Scopes[f]
121                 b, prev := fileScope.LookupParent(r.to, token.NoPos)
122                 if b == fileScope {
123                         r.errorf(from.Pos(), "renaming this %s %q to %q would conflict", objectKind(from), from.Name(), r.to)
124                         var prevPos token.Pos
125                         if prev != nil {
126                                 prevPos = prev.Pos()
127                         }
128                         r.errorf(prevPos, "\twith this %s", objectKind(prev))
129                         return // since checkInPackageBlock would report redundant errors
130                 }
131         }
132
133         // Check for conflicts in lexical scope.
134         if from.Exported() {
135                 for _, pkg := range r.packages {
136                         r.checkInLexicalScope(from, pkg)
137                 }
138         } else {
139                 r.checkInLexicalScope(from, pkg)
140         }
141 }
142
143 func (r *renamer) checkInLocalScope(from types.Object) {
144         pkg := r.packages[from.Pkg()]
145         r.checkInLexicalScope(from, pkg)
146 }
147
148 // checkInLexicalScope performs safety checks that a renaming does not
149 // change the lexical reference structure of the specified package.
150 //
151 // For objects in lexical scope, there are three kinds of conflicts:
152 // same-, sub-, and super-block conflicts.  We will illustrate all three
153 // using this example:
154 //
155 //      var x int
156 //      var z int
157 //
158 //      func f(y int) {
159 //              print(x)
160 //              print(y)
161 //      }
162 //
163 // Renaming x to z encounters a SAME-BLOCK CONFLICT, because an object
164 // with the new name already exists, defined in the same lexical block
165 // as the old object.
166 //
167 // Renaming x to y encounters a SUB-BLOCK CONFLICT, because there exists
168 // a reference to x from within (what would become) a hole in its scope.
169 // The definition of y in an (inner) sub-block would cast a shadow in
170 // the scope of the renamed variable.
171 //
172 // Renaming y to x encounters a SUPER-BLOCK CONFLICT.  This is the
173 // converse situation: there is an existing definition of the new name
174 // (x) in an (enclosing) super-block, and the renaming would create a
175 // hole in its scope, within which there exist references to it.  The
176 // new name casts a shadow in scope of the existing definition of x in
177 // the super-block.
178 //
179 // Removing the old name (and all references to it) is always safe, and
180 // requires no checks.
181 //
182 func (r *renamer) checkInLexicalScope(from types.Object, pkg Package) {
183         b := from.Parent() // the block defining the 'from' object
184         if b != nil {
185                 toBlock, to := b.LookupParent(r.to, from.Parent().End())
186                 if toBlock == b {
187                         // same-block conflict
188                         r.errorf(from.Pos(), "renaming this %s %q to %q",
189                                 objectKind(from), from.Name(), r.to)
190                         r.errorf(to.Pos(), "\tconflicts with %s in same block",
191                                 objectKind(to))
192                         return
193                 } else if toBlock != nil {
194                         // Check for super-block conflict.
195                         // The name r.to is defined in a superblock.
196                         // Is that name referenced from within this block?
197                         forEachLexicalRef(pkg, to, func(id *ast.Ident, block *types.Scope) bool {
198                                 _, obj := lexicalLookup(block, from.Name(), id.Pos())
199                                 if obj == from {
200                                         // super-block conflict
201                                         r.errorf(from.Pos(), "renaming this %s %q to %q",
202                                                 objectKind(from), from.Name(), r.to)
203                                         r.errorf(id.Pos(), "\twould shadow this reference")
204                                         r.errorf(to.Pos(), "\tto the %s declared here",
205                                                 objectKind(to))
206                                         return false // stop
207                                 }
208                                 return true
209                         })
210                 }
211         }
212         // Check for sub-block conflict.
213         // Is there an intervening definition of r.to between
214         // the block defining 'from' and some reference to it?
215         forEachLexicalRef(pkg, from, func(id *ast.Ident, block *types.Scope) bool {
216                 // Find the block that defines the found reference.
217                 // It may be an ancestor.
218                 fromBlock, _ := lexicalLookup(block, from.Name(), id.Pos())
219
220                 // See what r.to would resolve to in the same scope.
221                 toBlock, to := lexicalLookup(block, r.to, id.Pos())
222                 if to != nil {
223                         // sub-block conflict
224                         if deeper(toBlock, fromBlock) {
225                                 r.errorf(from.Pos(), "renaming this %s %q to %q",
226                                         objectKind(from), from.Name(), r.to)
227                                 r.errorf(id.Pos(), "\twould cause this reference to become shadowed")
228                                 r.errorf(to.Pos(), "\tby this intervening %s definition",
229                                         objectKind(to))
230                                 return false // stop
231                         }
232                 }
233                 return true
234         })
235
236         // Renaming a type that is used as an embedded field
237         // requires renaming the field too. e.g.
238         //      type T int // if we rename this to U..
239         //      var s struct {T}
240         //      print(s.T) // ...this must change too
241         if _, ok := from.(*types.TypeName); ok {
242                 for id, obj := range pkg.GetTypesInfo().Uses {
243                         if obj == from {
244                                 if field := pkg.GetTypesInfo().Defs[id]; field != nil {
245                                         r.check(field)
246                                 }
247                         }
248                 }
249         }
250 }
251
252 // lexicalLookup is like (*types.Scope).LookupParent but respects the
253 // environment visible at pos.  It assumes the relative position
254 // information is correct with each file.
255 func lexicalLookup(block *types.Scope, name string, pos token.Pos) (*types.Scope, types.Object) {
256         for b := block; b != nil; b = b.Parent() {
257                 obj := b.Lookup(name)
258                 // The scope of a package-level object is the entire package,
259                 // so ignore pos in that case.
260                 // No analogous clause is needed for file-level objects
261                 // since no reference can appear before an import decl.
262                 if obj == nil || obj.Pkg() == nil {
263                         continue
264                 }
265                 if b == obj.Pkg().Scope() || obj.Pos() < pos {
266                         return b, obj
267                 }
268         }
269         return nil, nil
270 }
271
272 // deeper reports whether block x is lexically deeper than y.
273 func deeper(x, y *types.Scope) bool {
274         if x == y || x == nil {
275                 return false
276         } else if y == nil {
277                 return true
278         } else {
279                 return deeper(x.Parent(), y.Parent())
280         }
281 }
282
283 // forEachLexicalRef calls fn(id, block) for each identifier id in package
284 // pkg that is a reference to obj in lexical scope.  block is the
285 // lexical block enclosing the reference.  If fn returns false the
286 // iteration is terminated and findLexicalRefs returns false.
287 func forEachLexicalRef(pkg Package, obj types.Object, fn func(id *ast.Ident, block *types.Scope) bool) bool {
288         ok := true
289         var stack []ast.Node
290
291         var visit func(n ast.Node) bool
292         visit = func(n ast.Node) bool {
293                 if n == nil {
294                         stack = stack[:len(stack)-1] // pop
295                         return false
296                 }
297                 if !ok {
298                         return false // bail out
299                 }
300
301                 stack = append(stack, n) // push
302                 switch n := n.(type) {
303                 case *ast.Ident:
304                         if pkg.GetTypesInfo().Uses[n] == obj {
305                                 block := enclosingBlock(pkg.GetTypesInfo(), stack)
306                                 if !fn(n, block) {
307                                         ok = false
308                                 }
309                         }
310                         return visit(nil) // pop stack
311
312                 case *ast.SelectorExpr:
313                         // don't visit n.Sel
314                         ast.Inspect(n.X, visit)
315                         return visit(nil) // pop stack, don't descend
316
317                 case *ast.CompositeLit:
318                         // Handle recursion ourselves for struct literals
319                         // so we don't visit field identifiers.
320                         tv, ok := pkg.GetTypesInfo().Types[n]
321                         if !ok {
322                                 return visit(nil) // pop stack, don't descend
323                         }
324                         if _, ok := Deref(tv.Type).Underlying().(*types.Struct); ok {
325                                 if n.Type != nil {
326                                         ast.Inspect(n.Type, visit)
327                                 }
328                                 for _, elt := range n.Elts {
329                                         if kv, ok := elt.(*ast.KeyValueExpr); ok {
330                                                 ast.Inspect(kv.Value, visit)
331                                         } else {
332                                                 ast.Inspect(elt, visit)
333                                         }
334                                 }
335                                 return visit(nil) // pop stack, don't descend
336                         }
337                 }
338                 return true
339         }
340
341         for _, f := range pkg.GetSyntax() {
342                 ast.Inspect(f, visit)
343                 if len(stack) != 0 {
344                         panic(stack)
345                 }
346                 if !ok {
347                         break
348                 }
349         }
350         return ok
351 }
352
353 // enclosingBlock returns the innermost block enclosing the specified
354 // AST node, specified in the form of a path from the root of the file,
355 // [file...n].
356 func enclosingBlock(info *types.Info, stack []ast.Node) *types.Scope {
357         for i := range stack {
358                 n := stack[len(stack)-1-i]
359                 // For some reason, go/types always associates a
360                 // function's scope with its FuncType.
361                 // TODO(adonovan): feature or a bug?
362                 switch f := n.(type) {
363                 case *ast.FuncDecl:
364                         n = f.Type
365                 case *ast.FuncLit:
366                         n = f.Type
367                 }
368                 if b := info.Scopes[n]; b != nil {
369                         return b
370                 }
371         }
372         panic("no Scope for *ast.File")
373 }
374
375 func (r *renamer) checkLabel(label *types.Label) {
376         // Check there are no identical labels in the function's label block.
377         // (Label blocks don't nest, so this is easy.)
378         if prev := label.Parent().Lookup(r.to); prev != nil {
379                 r.errorf(label.Pos(), "renaming this label %q to %q", label.Name(), prev.Name())
380                 r.errorf(prev.Pos(), "\twould conflict with this one")
381         }
382 }
383
384 // checkStructField checks that the field renaming will not cause
385 // conflicts at its declaration, or ambiguity or changes to any selection.
386 func (r *renamer) checkStructField(from *types.Var) {
387         // Check that the struct declaration is free of field conflicts,
388         // and field/method conflicts.
389
390         // go/types offers no easy way to get from a field (or interface
391         // method) to its declaring struct (or interface), so we must
392         // ascend the AST.
393         fromPkg, ok := r.packages[from.Pkg()]
394         if !ok {
395                 return
396         }
397         pkg, path, _ := pathEnclosingInterval(r.fset, fromPkg, from.Pos(), from.Pos())
398         if pkg == nil || path == nil {
399                 return
400         }
401         // path matches this pattern:
402         // [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File]
403
404         // Ascend to FieldList.
405         var i int
406         for {
407                 if _, ok := path[i].(*ast.FieldList); ok {
408                         break
409                 }
410                 i++
411         }
412         i++
413         tStruct := path[i].(*ast.StructType)
414         i++
415         // Ascend past parens (unlikely).
416         for {
417                 _, ok := path[i].(*ast.ParenExpr)
418                 if !ok {
419                         break
420                 }
421                 i++
422         }
423         if spec, ok := path[i].(*ast.TypeSpec); ok {
424                 // This struct is also a named type.
425                 // We must check for direct (non-promoted) field/field
426                 // and method/field conflicts.
427                 named := pkg.GetTypesInfo().Defs[spec.Name].Type()
428                 prev, indices, _ := types.LookupFieldOrMethod(named, true, pkg.GetTypes(), r.to)
429                 if len(indices) == 1 {
430                         r.errorf(from.Pos(), "renaming this field %q to %q",
431                                 from.Name(), r.to)
432                         r.errorf(prev.Pos(), "\twould conflict with this %s",
433                                 objectKind(prev))
434                         return // skip checkSelections to avoid redundant errors
435                 }
436         } else {
437                 // This struct is not a named type.
438                 // We need only check for direct (non-promoted) field/field conflicts.
439                 T := pkg.GetTypesInfo().Types[tStruct].Type.Underlying().(*types.Struct)
440                 for i := 0; i < T.NumFields(); i++ {
441                         if prev := T.Field(i); prev.Name() == r.to {
442                                 r.errorf(from.Pos(), "renaming this field %q to %q",
443                                         from.Name(), r.to)
444                                 r.errorf(prev.Pos(), "\twould conflict with this field")
445                                 return // skip checkSelections to avoid redundant errors
446                         }
447                 }
448         }
449
450         // Renaming an anonymous field requires renaming the type too. e.g.
451         //      print(s.T)       // if we rename T to U,
452         //      type T int       // this and
453         //      var s struct {T} // this must change too.
454         if from.Anonymous() {
455                 if named, ok := from.Type().(*types.Named); ok {
456                         r.check(named.Obj())
457                 } else if named, ok := Deref(from.Type()).(*types.Named); ok {
458                         r.check(named.Obj())
459                 }
460         }
461
462         // Check integrity of existing (field and method) selections.
463         r.checkSelections(from)
464 }
465
466 // checkSelection checks that all uses and selections that resolve to
467 // the specified object would continue to do so after the renaming.
468 func (r *renamer) checkSelections(from types.Object) {
469         for typ, pkg := range r.packages {
470                 if id := someUse(pkg.GetTypesInfo(), from); id != nil {
471                         if !r.checkExport(id, typ, from) {
472                                 return
473                         }
474                 }
475
476                 for syntax, sel := range pkg.GetTypesInfo().Selections {
477                         // There may be extant selections of only the old
478                         // name or only the new name, so we must check both.
479                         // (If neither, the renaming is sound.)
480                         //
481                         // In both cases, we wish to compare the lengths
482                         // of the implicit field path (Selection.Index)
483                         // to see if the renaming would change it.
484                         //
485                         // If a selection that resolves to 'from', when renamed,
486                         // would yield a path of the same or shorter length,
487                         // this indicates ambiguity or a changed referent,
488                         // analogous to same- or sub-block lexical conflict.
489                         //
490                         // If a selection using the name 'to' would
491                         // yield a path of the same or shorter length,
492                         // this indicates ambiguity or shadowing,
493                         // analogous to same- or super-block lexical conflict.
494
495                         // TODO(adonovan): fix: derive from Types[syntax.X].Mode
496                         // TODO(adonovan): test with pointer, value, addressable value.
497                         isAddressable := true
498
499                         if sel.Obj() == from {
500                                 if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), r.to); obj != nil {
501                                         // Renaming this existing selection of
502                                         // 'from' may block access to an existing
503                                         // type member named 'to'.
504                                         delta := len(indices) - len(sel.Index())
505                                         if delta > 0 {
506                                                 continue // no ambiguity
507                                         }
508                                         r.selectionConflict(from, delta, syntax, obj)
509                                         return
510                                 }
511                         } else if sel.Obj().Name() == r.to {
512                                 if obj, indices, _ := types.LookupFieldOrMethod(sel.Recv(), isAddressable, from.Pkg(), from.Name()); obj == from {
513                                         // Renaming 'from' may cause this existing
514                                         // selection of the name 'to' to change
515                                         // its meaning.
516                                         delta := len(indices) - len(sel.Index())
517                                         if delta > 0 {
518                                                 continue //  no ambiguity
519                                         }
520                                         r.selectionConflict(from, -delta, syntax, sel.Obj())
521                                         return
522                                 }
523                         }
524                 }
525         }
526 }
527
528 func (r *renamer) selectionConflict(from types.Object, delta int, syntax *ast.SelectorExpr, obj types.Object) {
529         r.errorf(from.Pos(), "renaming this %s %q to %q",
530                 objectKind(from), from.Name(), r.to)
531
532         switch {
533         case delta < 0:
534                 // analogous to sub-block conflict
535                 r.errorf(syntax.Sel.Pos(),
536                         "\twould change the referent of this selection")
537                 r.errorf(obj.Pos(), "\tof this %s", objectKind(obj))
538         case delta == 0:
539                 // analogous to same-block conflict
540                 r.errorf(syntax.Sel.Pos(),
541                         "\twould make this reference ambiguous")
542                 r.errorf(obj.Pos(), "\twith this %s", objectKind(obj))
543         case delta > 0:
544                 // analogous to super-block conflict
545                 r.errorf(syntax.Sel.Pos(),
546                         "\twould shadow this selection")
547                 r.errorf(obj.Pos(), "\tof the %s declared here",
548                         objectKind(obj))
549         }
550 }
551
552 // checkMethod performs safety checks for renaming a method.
553 // There are three hazards:
554 // - declaration conflicts
555 // - selection ambiguity/changes
556 // - entailed renamings of assignable concrete/interface types.
557 //   We reject renamings initiated at concrete methods if it would
558 //   change the assignability relation.  For renamings of abstract
559 //   methods, we rename all methods transitively coupled to it via
560 //   assignability.
561 func (r *renamer) checkMethod(from *types.Func) {
562         // e.g. error.Error
563         if from.Pkg() == nil {
564                 r.errorf(from.Pos(), "you cannot rename built-in method %s", from)
565                 return
566         }
567
568         // ASSIGNABILITY: We reject renamings of concrete methods that
569         // would break a 'satisfy' constraint; but renamings of abstract
570         // methods are allowed to proceed, and we rename affected
571         // concrete and abstract methods as necessary.  It is the
572         // initial method that determines the policy.
573
574         // Check for conflict at point of declaration.
575         // Check to ensure preservation of assignability requirements.
576         R := recv(from).Type()
577         if IsInterface(R) {
578                 // Abstract method
579
580                 // declaration
581                 prev, _, _ := types.LookupFieldOrMethod(R, false, from.Pkg(), r.to)
582                 if prev != nil {
583                         r.errorf(from.Pos(), "renaming this interface method %q to %q",
584                                 from.Name(), r.to)
585                         r.errorf(prev.Pos(), "\twould conflict with this method")
586                         return
587                 }
588
589                 // Check all interfaces that embed this one for
590                 // declaration conflicts too.
591                 for _, pkg := range r.packages {
592                         // Start with named interface types (better errors)
593                         for _, obj := range pkg.GetTypesInfo().Defs {
594                                 if obj, ok := obj.(*types.TypeName); ok && IsInterface(obj.Type()) {
595                                         f, _, _ := types.LookupFieldOrMethod(
596                                                 obj.Type(), false, from.Pkg(), from.Name())
597                                         if f == nil {
598                                                 continue
599                                         }
600                                         t, _, _ := types.LookupFieldOrMethod(
601                                                 obj.Type(), false, from.Pkg(), r.to)
602                                         if t == nil {
603                                                 continue
604                                         }
605                                         r.errorf(from.Pos(), "renaming this interface method %q to %q",
606                                                 from.Name(), r.to)
607                                         r.errorf(t.Pos(), "\twould conflict with this method")
608                                         r.errorf(obj.Pos(), "\tin named interface type %q", obj.Name())
609                                 }
610                         }
611
612                         // Now look at all literal interface types (includes named ones again).
613                         for e, tv := range pkg.GetTypesInfo().Types {
614                                 if e, ok := e.(*ast.InterfaceType); ok {
615                                         _ = e
616                                         _ = tv.Type.(*types.Interface)
617                                         // TODO(adonovan): implement same check as above.
618                                 }
619                         }
620                 }
621
622                 // assignability
623                 //
624                 // Find the set of concrete or abstract methods directly
625                 // coupled to abstract method 'from' by some
626                 // satisfy.Constraint, and rename them too.
627                 for key := range r.satisfy() {
628                         // key = (lhs, rhs) where lhs is always an interface.
629
630                         lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
631                         if lsel == nil {
632                                 continue
633                         }
634                         rmethods := r.msets.MethodSet(key.RHS)
635                         rsel := rmethods.Lookup(from.Pkg(), from.Name())
636                         if rsel == nil {
637                                 continue
638                         }
639
640                         // If both sides have a method of this name,
641                         // and one of them is m, the other must be coupled.
642                         var coupled *types.Func
643                         switch from {
644                         case lsel.Obj():
645                                 coupled = rsel.Obj().(*types.Func)
646                         case rsel.Obj():
647                                 coupled = lsel.Obj().(*types.Func)
648                         default:
649                                 continue
650                         }
651
652                         // We must treat concrete-to-interface
653                         // constraints like an implicit selection C.f of
654                         // each interface method I.f, and check that the
655                         // renaming leaves the selection unchanged and
656                         // unambiguous.
657                         //
658                         // Fun fact: the implicit selection of C.f
659                         //      type I interface{f()}
660                         //      type C struct{I}
661                         //      func (C) g()
662                         //      var _ I = C{} // here
663                         // yields abstract method I.f.  This can make error
664                         // messages less than obvious.
665                         //
666                         if !IsInterface(key.RHS) {
667                                 // The logic below was derived from checkSelections.
668
669                                 rtosel := rmethods.Lookup(from.Pkg(), r.to)
670                                 if rtosel != nil {
671                                         rto := rtosel.Obj().(*types.Func)
672                                         delta := len(rsel.Index()) - len(rtosel.Index())
673                                         if delta < 0 {
674                                                 continue // no ambiguity
675                                         }
676
677                                         // TODO(adonovan): record the constraint's position.
678                                         keyPos := token.NoPos
679
680                                         r.errorf(from.Pos(), "renaming this method %q to %q",
681                                                 from.Name(), r.to)
682                                         if delta == 0 {
683                                                 // analogous to same-block conflict
684                                                 r.errorf(keyPos, "\twould make the %s method of %s invoked via interface %s ambiguous",
685                                                         r.to, key.RHS, key.LHS)
686                                                 r.errorf(rto.Pos(), "\twith (%s).%s",
687                                                         recv(rto).Type(), r.to)
688                                         } else {
689                                                 // analogous to super-block conflict
690                                                 r.errorf(keyPos, "\twould change the %s method of %s invoked via interface %s",
691                                                         r.to, key.RHS, key.LHS)
692                                                 r.errorf(coupled.Pos(), "\tfrom (%s).%s",
693                                                         recv(coupled).Type(), r.to)
694                                                 r.errorf(rto.Pos(), "\tto (%s).%s",
695                                                         recv(rto).Type(), r.to)
696                                         }
697                                         return // one error is enough
698                                 }
699                         }
700
701                         if !r.changeMethods {
702                                 // This should be unreachable.
703                                 r.errorf(from.Pos(), "internal error: during renaming of abstract method %s", from)
704                                 r.errorf(coupled.Pos(), "\tchangedMethods=false, coupled method=%s", coupled)
705                                 r.errorf(from.Pos(), "\tPlease file a bug report")
706                                 return
707                         }
708
709                         // Rename the coupled method to preserve assignability.
710                         r.check(coupled)
711                 }
712         } else {
713                 // Concrete method
714
715                 // declaration
716                 prev, indices, _ := types.LookupFieldOrMethod(R, true, from.Pkg(), r.to)
717                 if prev != nil && len(indices) == 1 {
718                         r.errorf(from.Pos(), "renaming this method %q to %q",
719                                 from.Name(), r.to)
720                         r.errorf(prev.Pos(), "\twould conflict with this %s",
721                                 objectKind(prev))
722                         return
723                 }
724
725                 // assignability
726                 //
727                 // Find the set of abstract methods coupled to concrete
728                 // method 'from' by some satisfy.Constraint, and rename
729                 // them too.
730                 //
731                 // Coupling may be indirect, e.g. I.f <-> C.f via type D.
732                 //
733                 //      type I interface {f()}
734                 //      type C int
735                 //      type (C) f()
736                 //      type D struct{C}
737                 //      var _ I = D{}
738                 //
739                 for key := range r.satisfy() {
740                         // key = (lhs, rhs) where lhs is always an interface.
741                         if IsInterface(key.RHS) {
742                                 continue
743                         }
744                         rsel := r.msets.MethodSet(key.RHS).Lookup(from.Pkg(), from.Name())
745                         if rsel == nil || rsel.Obj() != from {
746                                 continue // rhs does not have the method
747                         }
748                         lsel := r.msets.MethodSet(key.LHS).Lookup(from.Pkg(), from.Name())
749                         if lsel == nil {
750                                 continue
751                         }
752                         imeth := lsel.Obj().(*types.Func)
753
754                         // imeth is the abstract method (e.g. I.f)
755                         // and key.RHS is the concrete coupling type (e.g. D).
756                         if !r.changeMethods {
757                                 r.errorf(from.Pos(), "renaming this method %q to %q",
758                                         from.Name(), r.to)
759                                 var pos token.Pos
760                                 var iface string
761
762                                 I := recv(imeth).Type()
763                                 if named, ok := I.(*types.Named); ok {
764                                         pos = named.Obj().Pos()
765                                         iface = "interface " + named.Obj().Name()
766                                 } else {
767                                         pos = from.Pos()
768                                         iface = I.String()
769                                 }
770                                 r.errorf(pos, "\twould make %s no longer assignable to %s",
771                                         key.RHS, iface)
772                                 r.errorf(imeth.Pos(), "\t(rename %s.%s if you intend to change both types)",
773                                         I, from.Name())
774                                 return // one error is enough
775                         }
776
777                         // Rename the coupled interface method to preserve assignability.
778                         r.check(imeth)
779                 }
780         }
781
782         // Check integrity of existing (field and method) selections.
783         // We skip this if there were errors above, to avoid redundant errors.
784         r.checkSelections(from)
785 }
786
787 func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
788         // Reject cross-package references if r.to is unexported.
789         // (Such references may be qualified identifiers or field/method
790         // selections.)
791         if !ast.IsExported(r.to) && pkg != from.Pkg() {
792                 r.errorf(from.Pos(),
793                         "renaming %q to %q would make it unexported",
794                         from.Name(), r.to)
795                 r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
796                         pkg.Path())
797                 return false
798         }
799         return true
800 }
801
802 // satisfy returns the set of interface satisfaction constraints.
803 func (r *renamer) satisfy() map[satisfy.Constraint]bool {
804         if r.satisfyConstraints == nil {
805                 // Compute on demand: it's expensive.
806                 var f satisfy.Finder
807                 for _, pkg := range r.packages {
808                         // From satisfy.Finder documentation:
809                         //
810                         // The package must be free of type errors, and
811                         // info.{Defs,Uses,Selections,Types} must have been populated by the
812                         // type-checker.
813                         //
814                         // Only proceed if all packages have no errors.
815                         if errs := pkg.GetErrors(); len(errs) > 0 {
816                                 r.errorf(token.NoPos, // we don't have a position for this error.
817                                         "renaming %q to %q not possible because %q has errors",
818                                         r.from, r.to, pkg.PkgPath())
819                                 return nil
820                         }
821                         f.Find(pkg.GetTypesInfo(), pkg.GetSyntax())
822                 }
823                 r.satisfyConstraints = f.Result
824         }
825         return r.satisfyConstraints
826 }
827
828 // -- helpers ----------------------------------------------------------
829
830 // recv returns the method's receiver.
831 func recv(meth *types.Func) *types.Var {
832         return meth.Type().(*types.Signature).Recv()
833 }
834
835 // someUse returns an arbitrary use of obj within info.
836 func someUse(info *types.Info, obj types.Object) *ast.Ident {
837         for id, o := range info.Uses {
838                 if o == obj {
839                         return id
840                 }
841         }
842         return nil
843 }
844
845 // pathEnclosingInterval returns the Package and ast.Node that
846 // contain source interval [start, end), and all the node's ancestors
847 // up to the AST root.  It searches all ast.Files of all packages.
848 // exact is defined as for astutil.PathEnclosingInterval.
849 //
850 // The zero value is returned if not found.
851 //
852 func pathEnclosingInterval(fset *token.FileSet, pkg Package, start, end token.Pos) (resPkg Package, path []ast.Node, exact bool) {
853         pkgs := []Package{pkg}
854         for _, f := range pkg.GetSyntax() {
855                 for _, imp := range f.Imports {
856                         if imp == nil {
857                                 continue
858                         }
859                         importPath, err := strconv.Unquote(imp.Path.Value)
860                         if err != nil {
861                                 continue
862                         }
863                         importPkg, err := pkg.GetImport(importPath)
864                         if err != nil {
865                                 return nil, nil, false
866                         }
867                         pkgs = append(pkgs, importPkg)
868                 }
869         }
870         for _, p := range pkgs {
871                 for _, f := range p.GetSyntax() {
872                         if f.Pos() == token.NoPos {
873                                 // This can happen if the parser saw
874                                 // too many errors and bailed out.
875                                 // (Use parser.AllErrors to prevent that.)
876                                 continue
877                         }
878                         if !tokenFileContainsPos(fset.File(f.Pos()), start) {
879                                 continue
880                         }
881                         if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
882                                 return pkg, path, exact
883                         }
884                 }
885         }
886         return nil, nil, false
887 }
888
889 // TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos)
890 func tokenFileContainsPos(f *token.File, pos token.Pos) bool {
891         p := int(pos)
892         base := f.Base()
893         return base <= p && p < base+f.Size()
894 }
895
896 func objectKind(obj types.Object) string {
897         switch obj := obj.(type) {
898         case *types.PkgName:
899                 return "imported package name"
900         case *types.TypeName:
901                 return "type"
902         case *types.Var:
903                 if obj.IsField() {
904                         return "field"
905                 }
906         case *types.Func:
907                 if obj.Type().(*types.Signature).Recv() != nil {
908                         return "method"
909                 }
910         }
911         // label, func, var, const
912         return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
913 }
914
915 // NB: for renamings, blank is not considered valid.
916 func isValidIdentifier(id string) bool {
917         if id == "" || id == "_" {
918                 return false
919         }
920         for i, r := range id {
921                 if !isLetter(r) && (i == 0 || !isDigit(r)) {
922                         return false
923                 }
924         }
925         return token.Lookup(id) == token.IDENT
926 }
927
928 // isLocal reports whether obj is local to some function.
929 // Precondition: not a struct field or interface method.
930 func isLocal(obj types.Object) bool {
931         // [... 5=stmt 4=func 3=file 2=pkg 1=universe]
932         var depth int
933         for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
934                 depth++
935         }
936         return depth >= 4
937 }
938
939 func isPackageLevel(obj types.Object) bool {
940         return obj.Pkg().Scope().Lookup(obj.Name()) == obj
941 }
942
943 // -- Plundered from go/scanner: ---------------------------------------
944
945 func isLetter(ch rune) bool {
946         return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
947 }
948
949 func isDigit(ch rune) bool {
950         return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
951 }