github.com/v2fly/tools@v0.100.0/internal/lsp/source/rename_check.go (about)

     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 github.com/v2fly/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  	"github.com/v2fly/tools/go/ast/astutil"
    20  	"github.com/v2fly/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 pkg.HasListOrParseErrors() || pkg.HasTypeErrors() {
   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  	if obj == nil {
   898  		return "nil object"
   899  	}
   900  	switch obj := obj.(type) {
   901  	case *types.PkgName:
   902  		return "imported package name"
   903  	case *types.TypeName:
   904  		return "type"
   905  	case *types.Var:
   906  		if obj.IsField() {
   907  			return "field"
   908  		}
   909  	case *types.Func:
   910  		if obj.Type().(*types.Signature).Recv() != nil {
   911  			return "method"
   912  		}
   913  	}
   914  	// label, func, var, const
   915  	return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types."))
   916  }
   917  
   918  // NB: for renamings, blank is not considered valid.
   919  func isValidIdentifier(id string) bool {
   920  	if id == "" || id == "_" {
   921  		return false
   922  	}
   923  	for i, r := range id {
   924  		if !isLetter(r) && (i == 0 || !isDigit(r)) {
   925  			return false
   926  		}
   927  	}
   928  	return token.Lookup(id) == token.IDENT
   929  }
   930  
   931  // isLocal reports whether obj is local to some function.
   932  // Precondition: not a struct field or interface method.
   933  func isLocal(obj types.Object) bool {
   934  	// [... 5=stmt 4=func 3=file 2=pkg 1=universe]
   935  	var depth int
   936  	for scope := obj.Parent(); scope != nil; scope = scope.Parent() {
   937  		depth++
   938  	}
   939  	return depth >= 4
   940  }
   941  
   942  func isPackageLevel(obj types.Object) bool {
   943  	if obj == nil {
   944  		return false
   945  	}
   946  	return obj.Pkg().Scope().Lookup(obj.Name()) == obj
   947  }
   948  
   949  // -- Plundered from go/scanner: ---------------------------------------
   950  
   951  func isLetter(ch rune) bool {
   952  	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
   953  }
   954  
   955  func isDigit(ch rune) bool {
   956  	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
   957  }