golang.org/x/tools/gopls@v0.15.3/internal/golang/rename.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  package golang
     6  
     7  // TODO(adonovan):
     8  //
     9  // - method of generic concrete type -> arbitrary instances of same
    10  //
    11  // - make satisfy work across packages.
    12  //
    13  // - tests, tests, tests:
    14  //   - play with renamings in the k8s tree.
    15  //   - generics
    16  //   - error cases (e.g. conflicts)
    17  //   - renaming a symbol declared in the module cache
    18  //     (currently proceeds with half of the renaming!)
    19  //   - make sure all tests have both a local and a cross-package analogue.
    20  //   - look at coverage
    21  //   - special cases: embedded fields, interfaces, test variants,
    22  //     function-local things with uppercase names;
    23  //     packages with type errors (currently 'satisfy' rejects them),
    24  //     package with missing imports;
    25  //
    26  // - measure performance in k8s.
    27  //
    28  // - The original gorename tool assumed well-typedness, but the gopls feature
    29  //   does no such check (which actually makes it much more useful).
    30  //   Audit to ensure it is safe on ill-typed code.
    31  //
    32  // - Generics support was no doubt buggy before but incrementalization
    33  //   may have exacerbated it. If the problem were just about objects,
    34  //   defs and uses it would be fairly simple, but type assignability
    35  //   comes into play in the 'satisfy' check for method renamings.
    36  //   De-instantiating Vector[int] to Vector[T] changes its type.
    37  //   We need to come up with a theory for the satisfy check that
    38  //   works with generics, and across packages. We currently have no
    39  //   simple way to pass types between packages (think: objectpath for
    40  //   types), though presumably exportdata could be pressed into service.
    41  //
    42  // - FileID-based de-duplication of edits to different URIs for the same file.
    43  
    44  import (
    45  	"context"
    46  	"errors"
    47  	"fmt"
    48  	"go/ast"
    49  	"go/token"
    50  	"go/types"
    51  	"path"
    52  	"path/filepath"
    53  	"regexp"
    54  	"sort"
    55  	"strconv"
    56  	"strings"
    57  
    58  	"golang.org/x/mod/modfile"
    59  	"golang.org/x/tools/go/ast/astutil"
    60  	"golang.org/x/tools/go/types/objectpath"
    61  	"golang.org/x/tools/go/types/typeutil"
    62  	"golang.org/x/tools/gopls/internal/cache"
    63  	"golang.org/x/tools/gopls/internal/cache/metadata"
    64  	"golang.org/x/tools/gopls/internal/cache/parsego"
    65  	"golang.org/x/tools/gopls/internal/file"
    66  	"golang.org/x/tools/gopls/internal/protocol"
    67  	"golang.org/x/tools/gopls/internal/util/bug"
    68  	"golang.org/x/tools/gopls/internal/util/safetoken"
    69  	"golang.org/x/tools/internal/diff"
    70  	"golang.org/x/tools/internal/event"
    71  	"golang.org/x/tools/internal/typeparams"
    72  	"golang.org/x/tools/refactor/satisfy"
    73  )
    74  
    75  // A renamer holds state of a single call to renameObj, which renames
    76  // an object (or several coupled objects) within a single type-checked
    77  // syntax package.
    78  type renamer struct {
    79  	pkg                *cache.Package        // the syntax package in which the renaming is applied
    80  	objsToUpdate       map[types.Object]bool // records progress of calls to check
    81  	conflicts          []string
    82  	from, to           string
    83  	satisfyConstraints map[satisfy.Constraint]bool
    84  	msets              typeutil.MethodSetCache
    85  	changeMethods      bool
    86  }
    87  
    88  // A PrepareItem holds the result of a "prepare rename" operation:
    89  // the source range and value of a selected identifier.
    90  type PrepareItem struct {
    91  	Range protocol.Range
    92  	Text  string
    93  }
    94  
    95  // PrepareRename searches for a valid renaming at position pp.
    96  //
    97  // The returned usererr is intended to be displayed to the user to explain why
    98  // the prepare fails. Probably we could eliminate the redundancy in returning
    99  // two errors, but for now this is done defensively.
   100  func PrepareRename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position) (_ *PrepareItem, usererr, err error) {
   101  	ctx, done := event.Start(ctx, "golang.PrepareRename")
   102  	defer done()
   103  
   104  	// Is the cursor within the package name declaration?
   105  	if pgf, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, pp); err != nil {
   106  		return nil, err, err
   107  	} else if inPackageName {
   108  		item, err := prepareRenamePackageName(ctx, snapshot, pgf)
   109  		return item, err, err
   110  	}
   111  
   112  	// Ordinary (non-package) renaming.
   113  	//
   114  	// Type-check the current package, locate the reference at the position,
   115  	// validate the object, and report its name and range.
   116  	//
   117  	// TODO(adonovan): in all cases below, we return usererr=nil,
   118  	// which means we return (nil, nil) at the protocol
   119  	// layer. This seems like a bug, or at best an exploitation of
   120  	// knowledge of VSCode-specific behavior. Can we avoid that?
   121  	pkg, pgf, err := NarrowestPackageForFile(ctx, snapshot, f.URI())
   122  	if err != nil {
   123  		return nil, nil, err
   124  	}
   125  	pos, err := pgf.PositionPos(pp)
   126  	if err != nil {
   127  		return nil, nil, err
   128  	}
   129  	targets, node, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
   130  	if err != nil {
   131  		return nil, nil, err
   132  	}
   133  	var obj types.Object
   134  	for obj = range targets {
   135  		break // pick one arbitrarily
   136  	}
   137  	if err := checkRenamable(obj); err != nil {
   138  		return nil, nil, err
   139  	}
   140  	rng, err := pgf.NodeRange(node)
   141  	if err != nil {
   142  		return nil, nil, err
   143  	}
   144  	if _, isImport := node.(*ast.ImportSpec); isImport {
   145  		// We're not really renaming the import path.
   146  		rng.End = rng.Start
   147  	}
   148  	return &PrepareItem{
   149  		Range: rng,
   150  		Text:  obj.Name(),
   151  	}, nil, nil
   152  }
   153  
   154  func prepareRenamePackageName(ctx context.Context, snapshot *cache.Snapshot, pgf *ParsedGoFile) (*PrepareItem, error) {
   155  	// Does the client support file renaming?
   156  	fileRenameSupported := false
   157  	for _, op := range snapshot.Options().SupportedResourceOperations {
   158  		if op == protocol.Rename {
   159  			fileRenameSupported = true
   160  			break
   161  		}
   162  	}
   163  	if !fileRenameSupported {
   164  		return nil, errors.New("can't rename package: LSP client does not support file renaming")
   165  	}
   166  
   167  	// Check validity of the metadata for the file's containing package.
   168  	meta, err := NarrowestMetadataForFile(ctx, snapshot, pgf.URI)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	if meta.Name == "main" {
   173  		return nil, fmt.Errorf("can't rename package \"main\"")
   174  	}
   175  	if strings.HasSuffix(string(meta.Name), "_test") {
   176  		return nil, fmt.Errorf("can't rename x_test packages")
   177  	}
   178  	if meta.Module == nil {
   179  		return nil, fmt.Errorf("can't rename package: missing module information for package %q", meta.PkgPath)
   180  	}
   181  	if meta.Module.Path == string(meta.PkgPath) {
   182  		return nil, fmt.Errorf("can't rename package: package path %q is the same as module path %q", meta.PkgPath, meta.Module.Path)
   183  	}
   184  
   185  	// Return the location of the package declaration.
   186  	rng, err := pgf.NodeRange(pgf.File.Name)
   187  	if err != nil {
   188  		return nil, err
   189  	}
   190  	return &PrepareItem{
   191  		Range: rng,
   192  		Text:  string(meta.Name),
   193  	}, nil
   194  }
   195  
   196  func checkRenamable(obj types.Object) error {
   197  	switch obj := obj.(type) {
   198  	case *types.Var:
   199  		if obj.Embedded() {
   200  			return fmt.Errorf("can't rename embedded fields: rename the type directly or name the field")
   201  		}
   202  	case *types.Builtin, *types.Nil:
   203  		return fmt.Errorf("%s is built in and cannot be renamed", obj.Name())
   204  	}
   205  	if obj.Pkg() == nil || obj.Pkg().Path() == "unsafe" {
   206  		// e.g. error.Error, unsafe.Pointer
   207  		return fmt.Errorf("%s is built in and cannot be renamed", obj.Name())
   208  	}
   209  	if obj.Name() == "_" {
   210  		return errors.New("can't rename \"_\"")
   211  	}
   212  	return nil
   213  }
   214  
   215  // Rename returns a map of TextEdits for each file modified when renaming a
   216  // given identifier within a package and a boolean value of true for renaming
   217  // package and false otherwise.
   218  func Rename(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position, newName string) (map[protocol.DocumentURI][]protocol.TextEdit, bool, error) {
   219  	ctx, done := event.Start(ctx, "golang.Rename")
   220  	defer done()
   221  
   222  	if !isValidIdentifier(newName) {
   223  		return nil, false, fmt.Errorf("invalid identifier to rename: %q", newName)
   224  	}
   225  
   226  	// Cursor within package name declaration?
   227  	_, inPackageName, err := parsePackageNameDecl(ctx, snapshot, f, pp)
   228  	if err != nil {
   229  		return nil, false, err
   230  	}
   231  
   232  	var editMap map[protocol.DocumentURI][]diff.Edit
   233  	if inPackageName {
   234  		editMap, err = renamePackageName(ctx, snapshot, f, PackageName(newName))
   235  	} else {
   236  		editMap, err = renameOrdinary(ctx, snapshot, f, pp, newName)
   237  	}
   238  	if err != nil {
   239  		return nil, false, err
   240  	}
   241  
   242  	// Convert edits to protocol form.
   243  	result := make(map[protocol.DocumentURI][]protocol.TextEdit)
   244  	for uri, edits := range editMap {
   245  		// Sort and de-duplicate edits.
   246  		//
   247  		// Overlapping edits may arise in local renamings (due
   248  		// to type switch implicits) and globals ones (due to
   249  		// processing multiple package variants).
   250  		//
   251  		// We assume renaming produces diffs that are all
   252  		// replacements (no adjacent insertions that might
   253  		// become reordered) and that are either identical or
   254  		// non-overlapping.
   255  		diff.SortEdits(edits)
   256  		filtered := edits[:0]
   257  		for i, edit := range edits {
   258  			if i == 0 || edit != filtered[len(filtered)-1] {
   259  				filtered = append(filtered, edit)
   260  			}
   261  		}
   262  		edits = filtered
   263  
   264  		// TODO(adonovan): the logic above handles repeat edits to the
   265  		// same file URI (e.g. as a member of package p and p_test) but
   266  		// is not sufficient to handle file-system level aliasing arising
   267  		// from symbolic or hard links. For that, we should use a
   268  		// robustio-FileID-keyed map.
   269  		// See https://go.dev/cl/457615 for example.
   270  		// This really occurs in practice, e.g. kubernetes has
   271  		// vendor/k8s.io/kubectl -> ../../staging/src/k8s.io/kubectl.
   272  		fh, err := snapshot.ReadFile(ctx, uri)
   273  		if err != nil {
   274  			return nil, false, err
   275  		}
   276  		data, err := fh.Content()
   277  		if err != nil {
   278  			return nil, false, err
   279  		}
   280  		m := protocol.NewMapper(uri, data)
   281  		protocolEdits, err := protocol.EditsFromDiffEdits(m, edits)
   282  		if err != nil {
   283  			return nil, false, err
   284  		}
   285  		result[uri] = protocolEdits
   286  	}
   287  
   288  	return result, inPackageName, nil
   289  }
   290  
   291  // renameOrdinary renames an ordinary (non-package) name throughout the workspace.
   292  func renameOrdinary(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp protocol.Position, newName string) (map[protocol.DocumentURI][]diff.Edit, error) {
   293  	// Type-check the referring package and locate the object(s).
   294  	//
   295  	// Unlike NarrowestPackageForFile, this operation prefers the
   296  	// widest variant as, for non-exported identifiers, it is the
   297  	// only package we need. (In case you're wondering why
   298  	// 'references' doesn't also want the widest variant: it
   299  	// computes the union across all variants.)
   300  	var targets map[types.Object]ast.Node
   301  	var pkg *cache.Package
   302  	{
   303  		mps, err := snapshot.MetadataForFile(ctx, f.URI())
   304  		if err != nil {
   305  			return nil, err
   306  		}
   307  		metadata.RemoveIntermediateTestVariants(&mps)
   308  		if len(mps) == 0 {
   309  			return nil, fmt.Errorf("no package metadata for file %s", f.URI())
   310  		}
   311  		widest := mps[len(mps)-1] // widest variant may include _test.go files
   312  		pkgs, err := snapshot.TypeCheck(ctx, widest.ID)
   313  		if err != nil {
   314  			return nil, err
   315  		}
   316  		pkg = pkgs[0]
   317  		pgf, err := pkg.File(f.URI())
   318  		if err != nil {
   319  			return nil, err // "can't happen"
   320  		}
   321  		pos, err := pgf.PositionPos(pp)
   322  		if err != nil {
   323  			return nil, err
   324  		}
   325  		objects, _, err := objectsAt(pkg.GetTypesInfo(), pgf.File, pos)
   326  		if err != nil {
   327  			return nil, err
   328  		}
   329  		targets = objects
   330  	}
   331  
   332  	// Pick a representative object arbitrarily.
   333  	// (All share the same name, pos, and kind.)
   334  	var obj types.Object
   335  	for obj = range targets {
   336  		break
   337  	}
   338  	if obj.Name() == newName {
   339  		return nil, fmt.Errorf("old and new names are the same: %s", newName)
   340  	}
   341  	if err := checkRenamable(obj); err != nil {
   342  		return nil, err
   343  	}
   344  
   345  	// Find objectpath, if object is exported ("" otherwise).
   346  	var declObjPath objectpath.Path
   347  	if obj.Exported() {
   348  		// objectpath.For requires the origin of a generic function or type, not an
   349  		// instantiation (a bug?). Unfortunately we can't call Func.Origin as this
   350  		// is not available in go/types@go1.18. So we take a scenic route.
   351  		//
   352  		// Note that unlike Funcs, TypeNames are always canonical (they are "left"
   353  		// of the type parameters, unlike methods).
   354  		switch obj.(type) { // avoid "obj :=" since cases reassign the var
   355  		case *types.TypeName:
   356  			if _, ok := obj.Type().(*types.TypeParam); ok {
   357  				// As with capitalized function parameters below, type parameters are
   358  				// local.
   359  				goto skipObjectPath
   360  			}
   361  		case *types.Func:
   362  			obj = funcOrigin(obj.(*types.Func))
   363  		case *types.Var:
   364  			// TODO(adonovan): do vars need the origin treatment too? (issue #58462)
   365  
   366  			// Function parameter and result vars that are (unusually)
   367  			// capitalized are technically exported, even though they
   368  			// cannot be referenced, because they may affect downstream
   369  			// error messages. But we can safely treat them as local.
   370  			//
   371  			// This is not merely an optimization: the renameExported
   372  			// operation gets confused by such vars. It finds them from
   373  			// objectpath, the classifies them as local vars, but as
   374  			// they came from export data they lack syntax and the
   375  			// correct scope tree (issue #61294).
   376  			if !obj.(*types.Var).IsField() && !isPackageLevel(obj) {
   377  				goto skipObjectPath
   378  			}
   379  		}
   380  		if path, err := objectpath.For(obj); err == nil {
   381  			declObjPath = path
   382  		}
   383  	skipObjectPath:
   384  	}
   385  
   386  	// Nonexported? Search locally.
   387  	if declObjPath == "" {
   388  		var objects []types.Object
   389  		for obj := range targets {
   390  			objects = append(objects, obj)
   391  		}
   392  		editMap, _, err := renameObjects(newName, pkg, objects...)
   393  		return editMap, err
   394  	}
   395  
   396  	// Exported: search globally.
   397  	//
   398  	// For exported package-level var/const/func/type objects, the
   399  	// search scope is just the direct importers.
   400  	//
   401  	// For exported fields and methods, the scope is the
   402  	// transitive rdeps. (The exportedness of the field's struct
   403  	// or method's receiver is irrelevant.)
   404  	transitive := false
   405  	switch obj := obj.(type) {
   406  	case *types.TypeName:
   407  		// Renaming an exported package-level type
   408  		// requires us to inspect all transitive rdeps
   409  		// in the event that the type is embedded.
   410  		//
   411  		// TODO(adonovan): opt: this is conservative
   412  		// but inefficient. Instead, expand the scope
   413  		// of the search only if we actually encounter
   414  		// an embedding of the type, and only then to
   415  		// the rdeps of the embedding package.
   416  		if obj.Parent() == obj.Pkg().Scope() {
   417  			transitive = true
   418  		}
   419  
   420  	case *types.Var:
   421  		if obj.IsField() {
   422  			transitive = true // field
   423  		}
   424  
   425  		// TODO(adonovan): opt: process only packages that
   426  		// contain a reference (xrefs) to the target field.
   427  
   428  	case *types.Func:
   429  		if obj.Type().(*types.Signature).Recv() != nil {
   430  			transitive = true // method
   431  		}
   432  
   433  		// It's tempting to optimize by skipping
   434  		// packages that don't contain a reference to
   435  		// the method in the xrefs index, but we still
   436  		// need to apply the satisfy check to those
   437  		// packages to find assignment statements that
   438  		// might expands the scope of the renaming.
   439  	}
   440  
   441  	// Type-check all the packages to inspect.
   442  	declURI := protocol.URIFromPath(pkg.FileSet().File(obj.Pos()).Name())
   443  	pkgs, err := typeCheckReverseDependencies(ctx, snapshot, declURI, transitive)
   444  	if err != nil {
   445  		return nil, err
   446  	}
   447  
   448  	// Apply the renaming to the (initial) object.
   449  	declPkgPath := PackagePath(obj.Pkg().Path())
   450  	return renameExported(pkgs, declPkgPath, declObjPath, newName)
   451  }
   452  
   453  // funcOrigin is a go1.18-portable implementation of (*types.Func).Origin.
   454  func funcOrigin(fn *types.Func) *types.Func {
   455  	// Method?
   456  	if fn.Type().(*types.Signature).Recv() != nil {
   457  		return typeparams.OriginMethod(fn)
   458  	}
   459  
   460  	// Package-level function?
   461  	// (Assume the origin has the same position.)
   462  	gen := fn.Pkg().Scope().Lookup(fn.Name())
   463  	if gen != nil && gen.Pos() == fn.Pos() {
   464  		return gen.(*types.Func)
   465  	}
   466  
   467  	return fn
   468  }
   469  
   470  // typeCheckReverseDependencies returns the type-checked packages for
   471  // the reverse dependencies of all packages variants containing
   472  // file declURI. The packages are in some topological order.
   473  //
   474  // It includes all variants (even intermediate test variants) for the
   475  // purposes of computing reverse dependencies, but discards ITVs for
   476  // the actual renaming work.
   477  //
   478  // (This neglects obscure edge cases where a _test.go file changes the
   479  // selectors used only in an ITV, but life is short. Also sin must be
   480  // punished.)
   481  func typeCheckReverseDependencies(ctx context.Context, snapshot *cache.Snapshot, declURI protocol.DocumentURI, transitive bool) ([]*cache.Package, error) {
   482  	variants, err := snapshot.MetadataForFile(ctx, declURI)
   483  	if err != nil {
   484  		return nil, err
   485  	}
   486  	// variants must include ITVs for the reverse dependency
   487  	// computation, but they are filtered out before we typecheck.
   488  	allRdeps := make(map[PackageID]*metadata.Package)
   489  	for _, variant := range variants {
   490  		rdeps, err := snapshot.ReverseDependencies(ctx, variant.ID, transitive)
   491  		if err != nil {
   492  			return nil, err
   493  		}
   494  		allRdeps[variant.ID] = variant // include self
   495  		for id, meta := range rdeps {
   496  			allRdeps[id] = meta
   497  		}
   498  	}
   499  	var ids []PackageID
   500  	for id, meta := range allRdeps {
   501  		if meta.IsIntermediateTestVariant() {
   502  			continue
   503  		}
   504  		ids = append(ids, id)
   505  	}
   506  
   507  	// Sort the packages into some topological order of the
   508  	// (unfiltered) metadata graph.
   509  	metadata.SortPostOrder(snapshot, ids)
   510  
   511  	// Dependencies must be visited first since they can expand
   512  	// the search set. Ideally we would process the (filtered) set
   513  	// of packages in the parallel postorder of the snapshot's
   514  	// (unfiltered) metadata graph, but this is quite tricky
   515  	// without a good graph abstraction.
   516  	//
   517  	// For now, we visit packages sequentially in order of
   518  	// ascending height, like an inverted breadth-first search.
   519  	//
   520  	// Type checking is by far the dominant cost, so
   521  	// overlapping it with renaming may not be worthwhile.
   522  	return snapshot.TypeCheck(ctx, ids...)
   523  }
   524  
   525  // renameExported renames the object denoted by (pkgPath, objPath)
   526  // within the specified packages, along with any other objects that
   527  // must be renamed as a consequence. The slice of packages must be
   528  // topologically ordered.
   529  func renameExported(pkgs []*cache.Package, declPkgPath PackagePath, declObjPath objectpath.Path, newName string) (map[protocol.DocumentURI][]diff.Edit, error) {
   530  
   531  	// A target is a name for an object that is stable across types.Packages.
   532  	type target struct {
   533  		pkg PackagePath
   534  		obj objectpath.Path
   535  	}
   536  
   537  	// Populate the initial set of target objects.
   538  	// This set may grow as we discover the consequences of each renaming.
   539  	//
   540  	// TODO(adonovan): strictly, each cone of reverse dependencies
   541  	// of a single variant should have its own target map that
   542  	// monotonically expands as we go up the import graph, because
   543  	// declarations in test files can alter the set of
   544  	// package-level names and change the meaning of field and
   545  	// method selectors. So if we parallelize the graph
   546  	// visitation (see above), we should also compute the targets
   547  	// as a union of dependencies.
   548  	//
   549  	// Or we could decide that the logic below is fast enough not
   550  	// to need parallelism. In small measurements so far the
   551  	// type-checking step is about 95% and the renaming only 5%.
   552  	targets := map[target]bool{{declPkgPath, declObjPath}: true}
   553  
   554  	// Apply the renaming operation to each package.
   555  	allEdits := make(map[protocol.DocumentURI][]diff.Edit)
   556  	for _, pkg := range pkgs {
   557  
   558  		// Resolved target objects within package pkg.
   559  		var objects []types.Object
   560  		for t := range targets {
   561  			p := pkg.DependencyTypes(t.pkg)
   562  			if p == nil {
   563  				continue // indirect dependency of no consequence
   564  			}
   565  			obj, err := objectpath.Object(p, t.obj)
   566  			if err != nil {
   567  				// Possibly a method or an unexported type
   568  				// that is not reachable through export data?
   569  				// See https://github.com/golang/go/issues/60789.
   570  				//
   571  				// TODO(adonovan): it seems unsatisfactory that Object
   572  				// should return an error for a "valid" path. Perhaps
   573  				// we should define such paths as invalid and make
   574  				// objectpath.For compute reachability?
   575  				// Would that be a compatible change?
   576  				continue
   577  			}
   578  			objects = append(objects, obj)
   579  		}
   580  		if len(objects) == 0 {
   581  			continue // no targets of consequence to this package
   582  		}
   583  
   584  		// Apply the renaming.
   585  		editMap, moreObjects, err := renameObjects(newName, pkg, objects...)
   586  		if err != nil {
   587  			return nil, err
   588  		}
   589  
   590  		// It is safe to concatenate the edits as they are non-overlapping
   591  		// (or identical, in which case they will be de-duped by Rename).
   592  		for uri, edits := range editMap {
   593  			allEdits[uri] = append(allEdits[uri], edits...)
   594  		}
   595  
   596  		// Expand the search set?
   597  		for obj := range moreObjects {
   598  			objpath, err := objectpath.For(obj)
   599  			if err != nil {
   600  				continue // not exported
   601  			}
   602  			target := target{PackagePath(obj.Pkg().Path()), objpath}
   603  			targets[target] = true
   604  
   605  			// TODO(adonovan): methods requires dynamic
   606  			// programming of the product targets x
   607  			// packages as any package might add a new
   608  			// target (from a foward dep) as a
   609  			// consequence, and any target might imply a
   610  			// new set of rdeps. See golang/go#58461.
   611  		}
   612  	}
   613  
   614  	return allEdits, nil
   615  }
   616  
   617  // renamePackageName renames package declarations, imports, and go.mod files.
   618  func renamePackageName(ctx context.Context, s *cache.Snapshot, f file.Handle, newName PackageName) (map[protocol.DocumentURI][]diff.Edit, error) {
   619  	// Rename the package decl and all imports.
   620  	renamingEdits, err := renamePackage(ctx, s, f, newName)
   621  	if err != nil {
   622  		return nil, err
   623  	}
   624  
   625  	// Update the last component of the file's enclosing directory.
   626  	oldBase := filepath.Dir(f.URI().Path())
   627  	newPkgDir := filepath.Join(filepath.Dir(oldBase), string(newName))
   628  
   629  	// Update any affected replace directives in go.mod files.
   630  	// TODO(adonovan): extract into its own function.
   631  	//
   632  	// Get all workspace modules.
   633  	// TODO(adonovan): should this operate on all go.mod files,
   634  	// irrespective of whether they are included in the workspace?
   635  	modFiles := s.View().ModFiles()
   636  	for _, m := range modFiles {
   637  		fh, err := s.ReadFile(ctx, m)
   638  		if err != nil {
   639  			return nil, err
   640  		}
   641  		pm, err := s.ParseMod(ctx, fh)
   642  		if err != nil {
   643  			return nil, err
   644  		}
   645  
   646  		modFileDir := filepath.Dir(pm.URI.Path())
   647  		affectedReplaces := []*modfile.Replace{}
   648  
   649  		// Check if any replace directives need to be fixed
   650  		for _, r := range pm.File.Replace {
   651  			if !strings.HasPrefix(r.New.Path, "/") && !strings.HasPrefix(r.New.Path, "./") && !strings.HasPrefix(r.New.Path, "../") {
   652  				continue
   653  			}
   654  
   655  			replacedPath := r.New.Path
   656  			if strings.HasPrefix(r.New.Path, "./") || strings.HasPrefix(r.New.Path, "../") {
   657  				replacedPath = filepath.Join(modFileDir, r.New.Path)
   658  			}
   659  
   660  			// TODO: Is there a risk of converting a '\' delimited replacement to a '/' delimited replacement?
   661  			if !strings.HasPrefix(filepath.ToSlash(replacedPath)+"/", filepath.ToSlash(oldBase)+"/") {
   662  				continue // not affected by the package renaming
   663  			}
   664  
   665  			affectedReplaces = append(affectedReplaces, r)
   666  		}
   667  
   668  		if len(affectedReplaces) == 0 {
   669  			continue
   670  		}
   671  		copied, err := modfile.Parse("", pm.Mapper.Content, nil)
   672  		if err != nil {
   673  			return nil, err
   674  		}
   675  
   676  		for _, r := range affectedReplaces {
   677  			replacedPath := r.New.Path
   678  			if strings.HasPrefix(r.New.Path, "./") || strings.HasPrefix(r.New.Path, "../") {
   679  				replacedPath = filepath.Join(modFileDir, r.New.Path)
   680  			}
   681  
   682  			suffix := strings.TrimPrefix(replacedPath, oldBase)
   683  
   684  			newReplacedPath, err := filepath.Rel(modFileDir, newPkgDir+suffix)
   685  			if err != nil {
   686  				return nil, err
   687  			}
   688  
   689  			newReplacedPath = filepath.ToSlash(newReplacedPath)
   690  
   691  			if !strings.HasPrefix(newReplacedPath, "/") && !strings.HasPrefix(newReplacedPath, "../") {
   692  				newReplacedPath = "./" + newReplacedPath
   693  			}
   694  
   695  			if err := copied.AddReplace(r.Old.Path, "", newReplacedPath, ""); err != nil {
   696  				return nil, err
   697  			}
   698  		}
   699  
   700  		copied.Cleanup()
   701  		newContent, err := copied.Format()
   702  		if err != nil {
   703  			return nil, err
   704  		}
   705  
   706  		// Calculate the edits to be made due to the change.
   707  		edits := diff.Bytes(pm.Mapper.Content, newContent)
   708  		renamingEdits[pm.URI] = append(renamingEdits[pm.URI], edits...)
   709  	}
   710  
   711  	return renamingEdits, nil
   712  }
   713  
   714  // renamePackage computes all workspace edits required to rename the package
   715  // described by the given metadata, to newName, by renaming its package
   716  // directory.
   717  //
   718  // It updates package clauses and import paths for the renamed package as well
   719  // as any other packages affected by the directory renaming among all packages
   720  // known to the snapshot.
   721  func renamePackage(ctx context.Context, s *cache.Snapshot, f file.Handle, newName PackageName) (map[protocol.DocumentURI][]diff.Edit, error) {
   722  	if strings.HasSuffix(string(newName), "_test") {
   723  		return nil, fmt.Errorf("cannot rename to _test package")
   724  	}
   725  
   726  	// We need metadata for the relevant package and module paths.
   727  	// These should be the same for all packages containing the file.
   728  	meta, err := NarrowestMetadataForFile(ctx, s, f.URI())
   729  	if err != nil {
   730  		return nil, err
   731  	}
   732  
   733  	oldPkgPath := meta.PkgPath
   734  	if meta.Module == nil {
   735  		return nil, fmt.Errorf("cannot rename package: missing module information for package %q", meta.PkgPath)
   736  	}
   737  	modulePath := PackagePath(meta.Module.Path)
   738  	if modulePath == oldPkgPath {
   739  		return nil, fmt.Errorf("cannot rename package: module path %q is the same as the package path, so renaming the package directory would have no effect", modulePath)
   740  	}
   741  
   742  	newPathPrefix := path.Join(path.Dir(string(oldPkgPath)), string(newName))
   743  
   744  	// We must inspect all packages, not just direct importers,
   745  	// because we also rename subpackages, which may be unrelated.
   746  	// (If the renamed package imports a subpackage it may require
   747  	// edits to both its package and import decls.)
   748  	allMetadata, err := s.AllMetadata(ctx)
   749  	if err != nil {
   750  		return nil, err
   751  	}
   752  
   753  	// Rename package and import declarations in all relevant packages.
   754  	edits := make(map[protocol.DocumentURI][]diff.Edit)
   755  	for _, mp := range allMetadata {
   756  		// Special case: x_test packages for the renamed package will not have the
   757  		// package path as a dir prefix, but still need their package clauses
   758  		// renamed.
   759  		if mp.PkgPath == oldPkgPath+"_test" {
   760  			if err := renamePackageClause(ctx, mp, s, newName+"_test", edits); err != nil {
   761  				return nil, err
   762  			}
   763  			continue
   764  		}
   765  
   766  		// Subtle: check this condition before checking for valid module info
   767  		// below, because we should not fail this operation if unrelated packages
   768  		// lack module info.
   769  		if !strings.HasPrefix(string(mp.PkgPath)+"/", string(oldPkgPath)+"/") {
   770  			continue // not affected by the package renaming
   771  		}
   772  
   773  		if mp.Module == nil {
   774  			// This check will always fail under Bazel.
   775  			return nil, fmt.Errorf("cannot rename package: missing module information for package %q", mp.PkgPath)
   776  		}
   777  
   778  		if modulePath != PackagePath(mp.Module.Path) {
   779  			continue // don't edit imports if nested package and renaming package have different module paths
   780  		}
   781  
   782  		// Renaming a package consists of changing its import path and package name.
   783  		suffix := strings.TrimPrefix(string(mp.PkgPath), string(oldPkgPath))
   784  		newPath := newPathPrefix + suffix
   785  
   786  		pkgName := mp.Name
   787  		if mp.PkgPath == oldPkgPath {
   788  			pkgName = newName
   789  
   790  			if err := renamePackageClause(ctx, mp, s, newName, edits); err != nil {
   791  				return nil, err
   792  			}
   793  		}
   794  
   795  		imp := ImportPath(newPath) // TODO(adonovan): what if newPath has vendor/ prefix?
   796  		if err := renameImports(ctx, s, mp, imp, pkgName, edits); err != nil {
   797  			return nil, err
   798  		}
   799  	}
   800  
   801  	return edits, nil
   802  }
   803  
   804  // renamePackageClause computes edits renaming the package clause of files in
   805  // the package described by the given metadata, to newName.
   806  //
   807  // Edits are written into the edits map.
   808  func renamePackageClause(ctx context.Context, mp *metadata.Package, snapshot *cache.Snapshot, newName PackageName, edits map[protocol.DocumentURI][]diff.Edit) error {
   809  	// Rename internal references to the package in the renaming package.
   810  	for _, uri := range mp.CompiledGoFiles {
   811  		fh, err := snapshot.ReadFile(ctx, uri)
   812  		if err != nil {
   813  			return err
   814  		}
   815  		f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
   816  		if err != nil {
   817  			return err
   818  		}
   819  		if f.File.Name == nil {
   820  			continue // no package declaration
   821  		}
   822  
   823  		edit, err := posEdit(f.Tok, f.File.Name.Pos(), f.File.Name.End(), string(newName))
   824  		if err != nil {
   825  			return err
   826  		}
   827  		edits[f.URI] = append(edits[f.URI], edit)
   828  	}
   829  
   830  	return nil
   831  }
   832  
   833  // renameImports computes the set of edits to imports resulting from renaming
   834  // the package described by the given metadata, to a package with import path
   835  // newPath and name newName.
   836  //
   837  // Edits are written into the edits map.
   838  func renameImports(ctx context.Context, snapshot *cache.Snapshot, mp *metadata.Package, newPath ImportPath, newName PackageName, allEdits map[protocol.DocumentURI][]diff.Edit) error {
   839  	rdeps, err := snapshot.ReverseDependencies(ctx, mp.ID, false) // find direct importers
   840  	if err != nil {
   841  		return err
   842  	}
   843  
   844  	// Pass 1: rename import paths in import declarations.
   845  	needsTypeCheck := make(map[PackageID][]protocol.DocumentURI)
   846  	for _, rdep := range rdeps {
   847  		if rdep.IsIntermediateTestVariant() {
   848  			continue // for renaming, these variants are redundant
   849  		}
   850  
   851  		for _, uri := range rdep.CompiledGoFiles {
   852  			fh, err := snapshot.ReadFile(ctx, uri)
   853  			if err != nil {
   854  				return err
   855  			}
   856  			f, err := snapshot.ParseGo(ctx, fh, ParseHeader)
   857  			if err != nil {
   858  				return err
   859  			}
   860  			if f.File.Name == nil {
   861  				continue // no package declaration
   862  			}
   863  			for _, imp := range f.File.Imports {
   864  				if rdep.DepsByImpPath[metadata.UnquoteImportPath(imp)] != mp.ID {
   865  					continue // not the import we're looking for
   866  				}
   867  
   868  				// If the import does not explicitly specify
   869  				// a local name, then we need to invoke the
   870  				// type checker to locate references to update.
   871  				//
   872  				// TODO(adonovan): is this actually true?
   873  				// Renaming an import with a local name can still
   874  				// cause conflicts: shadowing of built-ins, or of
   875  				// package-level decls in the same or another file.
   876  				if imp.Name == nil {
   877  					needsTypeCheck[rdep.ID] = append(needsTypeCheck[rdep.ID], uri)
   878  				}
   879  
   880  				// Create text edit for the import path (string literal).
   881  				edit, err := posEdit(f.Tok, imp.Path.Pos(), imp.Path.End(), strconv.Quote(string(newPath)))
   882  				if err != nil {
   883  					return err
   884  				}
   885  				allEdits[uri] = append(allEdits[uri], edit)
   886  			}
   887  		}
   888  	}
   889  
   890  	// If the imported package's name hasn't changed,
   891  	// we don't need to rename references within each file.
   892  	if newName == mp.Name {
   893  		return nil
   894  	}
   895  
   896  	// Pass 2: rename local name (types.PkgName) of imported
   897  	// package throughout one or more files of the package.
   898  	ids := make([]PackageID, 0, len(needsTypeCheck))
   899  	for id := range needsTypeCheck {
   900  		ids = append(ids, id)
   901  	}
   902  	pkgs, err := snapshot.TypeCheck(ctx, ids...)
   903  	if err != nil {
   904  		return err
   905  	}
   906  	for i, id := range ids {
   907  		pkg := pkgs[i]
   908  		for _, uri := range needsTypeCheck[id] {
   909  			f, err := pkg.File(uri)
   910  			if err != nil {
   911  				return err
   912  			}
   913  			for _, imp := range f.File.Imports {
   914  				if imp.Name != nil {
   915  					continue // has explicit local name
   916  				}
   917  				if rdeps[id].DepsByImpPath[metadata.UnquoteImportPath(imp)] != mp.ID {
   918  					continue // not the import we're looking for
   919  				}
   920  
   921  				pkgname := pkg.GetTypesInfo().Implicits[imp].(*types.PkgName)
   922  
   923  				pkgScope := pkg.GetTypes().Scope()
   924  				fileScope := pkg.GetTypesInfo().Scopes[f.File]
   925  
   926  				localName := string(newName)
   927  				try := 0
   928  
   929  				// Keep trying with fresh names until one succeeds.
   930  				//
   931  				// TODO(adonovan): fix: this loop is not sufficient to choose a name
   932  				// that is guaranteed to be conflict-free; renameObj may still fail.
   933  				// So the retry loop should be around renameObj, and we shouldn't
   934  				// bother with scopes here.
   935  				for fileScope.Lookup(localName) != nil || pkgScope.Lookup(localName) != nil {
   936  					try++
   937  					localName = fmt.Sprintf("%s%d", newName, try)
   938  				}
   939  
   940  				// renameObj detects various conflicts, including:
   941  				// - new name conflicts with a package-level decl in this file;
   942  				// - new name hides a package-level decl in another file that
   943  				//   is actually referenced in this file;
   944  				// - new name hides a built-in that is actually referenced
   945  				//   in this file;
   946  				// - a reference in this file to the old package name would
   947  				//   become shadowed by an intervening declaration that
   948  				//   uses the new name.
   949  				// It returns the edits if no conflict was detected.
   950  				editMap, _, err := renameObjects(localName, pkg, pkgname)
   951  				if err != nil {
   952  					return err
   953  				}
   954  
   955  				// If the chosen local package name matches the package's
   956  				// new name, delete the change that would have inserted
   957  				// an explicit local name, which is always the lexically
   958  				// first change.
   959  				if localName == string(newName) {
   960  					edits, ok := editMap[uri]
   961  					if !ok {
   962  						return fmt.Errorf("internal error: no changes for %s", uri)
   963  					}
   964  					diff.SortEdits(edits)
   965  					editMap[uri] = edits[1:]
   966  				}
   967  				for uri, edits := range editMap {
   968  					allEdits[uri] = append(allEdits[uri], edits...)
   969  				}
   970  			}
   971  		}
   972  	}
   973  	return nil
   974  }
   975  
   976  // renameObjects computes the edits to the type-checked syntax package pkg
   977  // required to rename a set of target objects to newName.
   978  //
   979  // It also returns the set of objects that were found (due to
   980  // corresponding methods and embedded fields) to require renaming as a
   981  // consequence of the requested renamings.
   982  //
   983  // It returns an error if the renaming would cause a conflict.
   984  func renameObjects(newName string, pkg *cache.Package, targets ...types.Object) (map[protocol.DocumentURI][]diff.Edit, map[types.Object]bool, error) {
   985  	r := renamer{
   986  		pkg:          pkg,
   987  		objsToUpdate: make(map[types.Object]bool),
   988  		from:         targets[0].Name(),
   989  		to:           newName,
   990  	}
   991  
   992  	// A renaming initiated at an interface method indicates the
   993  	// intention to rename abstract and concrete methods as needed
   994  	// to preserve assignability.
   995  	// TODO(adonovan): pull this into the caller.
   996  	for _, obj := range targets {
   997  		if obj, ok := obj.(*types.Func); ok {
   998  			recv := obj.Type().(*types.Signature).Recv()
   999  			if recv != nil && types.IsInterface(recv.Type().Underlying()) {
  1000  				r.changeMethods = true
  1001  				break
  1002  			}
  1003  		}
  1004  	}
  1005  
  1006  	// Check that the renaming of the identifier is ok.
  1007  	for _, obj := range targets {
  1008  		r.check(obj)
  1009  		if len(r.conflicts) > 0 {
  1010  			// Stop at first error.
  1011  			return nil, nil, fmt.Errorf("%s", strings.Join(r.conflicts, "\n"))
  1012  		}
  1013  	}
  1014  
  1015  	editMap, err := r.update()
  1016  	if err != nil {
  1017  		return nil, nil, err
  1018  	}
  1019  
  1020  	// Remove initial targets so that only 'consequences' remain.
  1021  	for _, obj := range targets {
  1022  		delete(r.objsToUpdate, obj)
  1023  	}
  1024  	return editMap, r.objsToUpdate, nil
  1025  }
  1026  
  1027  // Rename all references to the target objects.
  1028  func (r *renamer) update() (map[protocol.DocumentURI][]diff.Edit, error) {
  1029  	result := make(map[protocol.DocumentURI][]diff.Edit)
  1030  
  1031  	// shouldUpdate reports whether obj is one of (or an
  1032  	// instantiation of one of) the target objects.
  1033  	shouldUpdate := func(obj types.Object) bool {
  1034  		return containsOrigin(r.objsToUpdate, obj)
  1035  	}
  1036  
  1037  	// Find all identifiers in the package that define or use a
  1038  	// renamed object. We iterate over info as it is more efficient
  1039  	// than calling ast.Inspect for each of r.pkg.CompiledGoFiles().
  1040  	type item struct {
  1041  		node  ast.Node // Ident, ImportSpec (obj=PkgName), or CaseClause (obj=Var)
  1042  		obj   types.Object
  1043  		isDef bool
  1044  	}
  1045  	var items []item
  1046  	info := r.pkg.GetTypesInfo()
  1047  	for id, obj := range info.Uses {
  1048  		if shouldUpdate(obj) {
  1049  			items = append(items, item{id, obj, false})
  1050  		}
  1051  	}
  1052  	for id, obj := range info.Defs {
  1053  		if shouldUpdate(obj) {
  1054  			items = append(items, item{id, obj, true})
  1055  		}
  1056  	}
  1057  	for node, obj := range info.Implicits {
  1058  		if shouldUpdate(obj) {
  1059  			switch node.(type) {
  1060  			case *ast.ImportSpec, *ast.CaseClause:
  1061  				items = append(items, item{node, obj, true})
  1062  			}
  1063  		}
  1064  	}
  1065  	sort.Slice(items, func(i, j int) bool {
  1066  		return items[i].node.Pos() < items[j].node.Pos()
  1067  	})
  1068  
  1069  	// Update each identifier, and its doc comment if it is a declaration.
  1070  	for _, item := range items {
  1071  		pgf, ok := enclosingFile(r.pkg, item.node.Pos())
  1072  		if !ok {
  1073  			bug.Reportf("edit does not belong to syntax of package %q", r.pkg)
  1074  			continue
  1075  		}
  1076  
  1077  		// Renaming a types.PkgName may result in the addition or removal of an identifier,
  1078  		// so we deal with this separately.
  1079  		if pkgName, ok := item.obj.(*types.PkgName); ok && item.isDef {
  1080  			edit, err := r.updatePkgName(pgf, pkgName)
  1081  			if err != nil {
  1082  				return nil, err
  1083  			}
  1084  			result[pgf.URI] = append(result[pgf.URI], edit)
  1085  			continue
  1086  		}
  1087  
  1088  		// Workaround the unfortunate lack of a Var object
  1089  		// for x in "switch x := expr.(type) {}" by adjusting
  1090  		// the case clause to the switch ident.
  1091  		// This may result in duplicate edits, but we de-dup later.
  1092  		if _, ok := item.node.(*ast.CaseClause); ok {
  1093  			path, _ := astutil.PathEnclosingInterval(pgf.File, item.obj.Pos(), item.obj.Pos())
  1094  			item.node = path[0].(*ast.Ident)
  1095  		}
  1096  
  1097  		// Replace the identifier with r.to.
  1098  		edit, err := posEdit(pgf.Tok, item.node.Pos(), item.node.End(), r.to)
  1099  		if err != nil {
  1100  			return nil, err
  1101  		}
  1102  
  1103  		result[pgf.URI] = append(result[pgf.URI], edit)
  1104  
  1105  		if !item.isDef { // uses do not have doc comments to update.
  1106  			continue
  1107  		}
  1108  
  1109  		doc := docComment(pgf, item.node.(*ast.Ident))
  1110  		if doc == nil {
  1111  			continue
  1112  		}
  1113  
  1114  		// Perform the rename in doc comments declared in the original package.
  1115  		// go/parser strips out \r\n returns from the comment text, so go
  1116  		// line-by-line through the comment text to get the correct positions.
  1117  		docRegexp := regexp.MustCompile(`\b` + r.from + `\b`) // valid identifier => valid regexp
  1118  		for _, comment := range doc.List {
  1119  			if isDirective(comment.Text) {
  1120  				continue
  1121  			}
  1122  			// TODO(adonovan): why are we looping over lines?
  1123  			// Just run the loop body once over the entire multiline comment.
  1124  			lines := strings.Split(comment.Text, "\n")
  1125  			tokFile := pgf.Tok
  1126  			commentLine := safetoken.Line(tokFile, comment.Pos())
  1127  			uri := protocol.URIFromPath(tokFile.Name())
  1128  			for i, line := range lines {
  1129  				lineStart := comment.Pos()
  1130  				if i > 0 {
  1131  					lineStart = tokFile.LineStart(commentLine + i)
  1132  				}
  1133  				for _, locs := range docRegexp.FindAllIndex([]byte(line), -1) {
  1134  					edit, err := posEdit(tokFile, lineStart+token.Pos(locs[0]), lineStart+token.Pos(locs[1]), r.to)
  1135  					if err != nil {
  1136  						return nil, err // can't happen
  1137  					}
  1138  					result[uri] = append(result[uri], edit)
  1139  				}
  1140  			}
  1141  		}
  1142  	}
  1143  
  1144  	docLinkEdits, err := r.updateCommentDocLinks()
  1145  	if err != nil {
  1146  		return nil, err
  1147  	}
  1148  	for uri, edits := range docLinkEdits {
  1149  		result[uri] = append(result[uri], edits...)
  1150  	}
  1151  
  1152  	return result, nil
  1153  }
  1154  
  1155  // updateCommentDocLinks updates each doc comment in the package
  1156  // that refers to one of the renamed objects using a doc link
  1157  // (https://golang.org/doc/comment#doclinks) such as "[pkg.Type.Method]".
  1158  func (r *renamer) updateCommentDocLinks() (map[protocol.DocumentURI][]diff.Edit, error) {
  1159  	result := make(map[protocol.DocumentURI][]diff.Edit)
  1160  	var docRenamers []*docLinkRenamer
  1161  	for obj := range r.objsToUpdate {
  1162  		if _, ok := obj.(*types.PkgName); ok {
  1163  			// The dot package name will not be referenced
  1164  			if obj.Name() == "." {
  1165  				continue
  1166  			}
  1167  
  1168  			docRenamers = append(docRenamers, &docLinkRenamer{
  1169  				isDep:       false,
  1170  				isPkgOrType: true,
  1171  				file:        r.pkg.FileSet().File(obj.Pos()),
  1172  				regexp:      docLinkPattern("", "", obj.Name(), true),
  1173  				to:          r.to,
  1174  			})
  1175  			continue
  1176  		}
  1177  		if !obj.Exported() {
  1178  			continue
  1179  		}
  1180  		recvName := ""
  1181  		// Doc links can reference only exported package-level objects
  1182  		// and methods of exported package-level named types.
  1183  		if !isPackageLevel(obj) {
  1184  			_, isFunc := obj.(*types.Func)
  1185  			if !isFunc {
  1186  				continue
  1187  			}
  1188  			recv := obj.Type().(*types.Signature).Recv()
  1189  			if recv == nil {
  1190  				continue
  1191  			}
  1192  			recvT := recv.Type()
  1193  			if ptr, ok := recvT.(*types.Pointer); ok {
  1194  				recvT = ptr.Elem()
  1195  			}
  1196  			named, isNamed := recvT.(*types.Named)
  1197  			if !isNamed {
  1198  				continue
  1199  			}
  1200  			// Doc links can't reference interface methods.
  1201  			if types.IsInterface(named.Underlying()) {
  1202  				continue
  1203  			}
  1204  			name := named.Origin().Obj()
  1205  			if !name.Exported() || !isPackageLevel(name) {
  1206  				continue
  1207  			}
  1208  			recvName = name.Name()
  1209  		}
  1210  
  1211  		// Qualify objects from other packages.
  1212  		pkgName := ""
  1213  		if r.pkg.GetTypes() != obj.Pkg() {
  1214  			pkgName = obj.Pkg().Name()
  1215  		}
  1216  		_, isTypeName := obj.(*types.TypeName)
  1217  		docRenamers = append(docRenamers, &docLinkRenamer{
  1218  			isDep:       r.pkg.GetTypes() != obj.Pkg(),
  1219  			isPkgOrType: isTypeName,
  1220  			packagePath: obj.Pkg().Path(),
  1221  			packageName: pkgName,
  1222  			recvName:    recvName,
  1223  			objName:     obj.Name(),
  1224  			regexp:      docLinkPattern(pkgName, recvName, obj.Name(), isTypeName),
  1225  			to:          r.to,
  1226  		})
  1227  	}
  1228  	for _, pgf := range r.pkg.CompiledGoFiles() {
  1229  		for _, d := range docRenamers {
  1230  			edits, err := d.update(pgf)
  1231  			if err != nil {
  1232  				return nil, err
  1233  			}
  1234  			if len(edits) > 0 {
  1235  				result[pgf.URI] = append(result[pgf.URI], edits...)
  1236  			}
  1237  		}
  1238  	}
  1239  	return result, nil
  1240  }
  1241  
  1242  // docLinkPattern returns a regular expression that matches doclinks in comments.
  1243  // It has one submatch that indicates the symbol to be updated.
  1244  func docLinkPattern(pkgName, recvName, objName string, isPkgOrType bool) *regexp.Regexp {
  1245  	// The doc link may contain a leading star, e.g. [*bytes.Buffer].
  1246  	pattern := `\[\*?`
  1247  	if pkgName != "" {
  1248  		pattern += pkgName + `\.`
  1249  	}
  1250  	if recvName != "" {
  1251  		pattern += recvName + `\.`
  1252  	}
  1253  	// The first submatch is object name.
  1254  	pattern += `(` + objName + `)`
  1255  	// If the object is a *types.TypeName or *types.PkgName, also need
  1256  	// match the objects referenced by them, so add `(\.\w+)*`.
  1257  	if isPkgOrType {
  1258  		pattern += `(?:\.\w+)*`
  1259  	}
  1260  	// There are two type of link in comments:
  1261  	//   1. url link. e.g. [text]: url
  1262  	//   2. doc link. e.g. [pkg.Name]
  1263  	// in order to only match the doc link, add `([^:]|$)` in the end.
  1264  	pattern += `\](?:[^:]|$)`
  1265  
  1266  	return regexp.MustCompile(pattern)
  1267  }
  1268  
  1269  // A docLinkRenamer renames doc links of forms such as these:
  1270  //
  1271  //	[Func]
  1272  //	[pkg.Func]
  1273  //	[RecvType.Method]
  1274  //	[*Type]
  1275  //	[*pkg.Type]
  1276  //	[*pkg.RecvType.Method]
  1277  type docLinkRenamer struct {
  1278  	isDep       bool // object is from a dependency package
  1279  	isPkgOrType bool // object is *types.PkgName or *types.TypeName
  1280  	packagePath string
  1281  	packageName string // e.g. "pkg"
  1282  	recvName    string // e.g. "RecvType"
  1283  	objName     string // e.g. "Func", "Type", "Method"
  1284  	to          string // new name
  1285  	regexp      *regexp.Regexp
  1286  
  1287  	file *token.File // enclosing file, if renaming *types.PkgName
  1288  }
  1289  
  1290  // update updates doc links in the package level comments.
  1291  func (r *docLinkRenamer) update(pgf *parsego.File) (result []diff.Edit, err error) {
  1292  	if r.file != nil && r.file != pgf.Tok {
  1293  		return nil, nil
  1294  	}
  1295  	pattern := r.regexp
  1296  	// If the object is in dependency package,
  1297  	// the imported name in the file may be different from the original package name
  1298  	if r.isDep {
  1299  		for _, spec := range pgf.File.Imports {
  1300  			importPath, _ := strconv.Unquote(spec.Path.Value)
  1301  			if importPath == r.packagePath {
  1302  				// Ignore blank imports
  1303  				if spec.Name == nil || spec.Name.Name == "_" || spec.Name.Name == "." {
  1304  					continue
  1305  				}
  1306  				if spec.Name.Name != r.packageName {
  1307  					pattern = docLinkPattern(spec.Name.Name, r.recvName, r.objName, r.isPkgOrType)
  1308  				}
  1309  				break
  1310  			}
  1311  		}
  1312  	}
  1313  
  1314  	var edits []diff.Edit
  1315  	updateDocLinks := func(doc *ast.CommentGroup) error {
  1316  		if doc != nil {
  1317  			for _, c := range doc.List {
  1318  				for _, locs := range pattern.FindAllStringSubmatchIndex(c.Text, -1) {
  1319  					// The first submatch is the object name, so the locs[2:4] is the index of object name.
  1320  					edit, err := posEdit(pgf.Tok, c.Pos()+token.Pos(locs[2]), c.Pos()+token.Pos(locs[3]), r.to)
  1321  					if err != nil {
  1322  						return err
  1323  					}
  1324  					edits = append(edits, edit)
  1325  				}
  1326  			}
  1327  		}
  1328  		return nil
  1329  	}
  1330  
  1331  	// Update package doc comments.
  1332  	err = updateDocLinks(pgf.File.Doc)
  1333  	if err != nil {
  1334  		return nil, err
  1335  	}
  1336  	for _, decl := range pgf.File.Decls {
  1337  		var doc *ast.CommentGroup
  1338  		switch decl := decl.(type) {
  1339  		case *ast.GenDecl:
  1340  			doc = decl.Doc
  1341  		case *ast.FuncDecl:
  1342  			doc = decl.Doc
  1343  		}
  1344  		err = updateDocLinks(doc)
  1345  		if err != nil {
  1346  			return nil, err
  1347  		}
  1348  	}
  1349  	return edits, nil
  1350  }
  1351  
  1352  // docComment returns the doc for an identifier within the specified file.
  1353  func docComment(pgf *ParsedGoFile, id *ast.Ident) *ast.CommentGroup {
  1354  	nodes, _ := astutil.PathEnclosingInterval(pgf.File, id.Pos(), id.End())
  1355  	for _, node := range nodes {
  1356  		switch decl := node.(type) {
  1357  		case *ast.FuncDecl:
  1358  			return decl.Doc
  1359  		case *ast.Field:
  1360  			return decl.Doc
  1361  		case *ast.GenDecl:
  1362  			return decl.Doc
  1363  		// For {Type,Value}Spec, if the doc on the spec is absent,
  1364  		// search for the enclosing GenDecl
  1365  		case *ast.TypeSpec:
  1366  			if decl.Doc != nil {
  1367  				return decl.Doc
  1368  			}
  1369  		case *ast.ValueSpec:
  1370  			if decl.Doc != nil {
  1371  				return decl.Doc
  1372  			}
  1373  		case *ast.Ident:
  1374  		case *ast.AssignStmt:
  1375  			// *ast.AssignStmt doesn't have an associated comment group.
  1376  			// So, we try to find a comment just before the identifier.
  1377  
  1378  			// Try to find a comment group only for short variable declarations (:=).
  1379  			if decl.Tok != token.DEFINE {
  1380  				return nil
  1381  			}
  1382  
  1383  			identLine := safetoken.Line(pgf.Tok, id.Pos())
  1384  			for _, comment := range nodes[len(nodes)-1].(*ast.File).Comments {
  1385  				if comment.Pos() > id.Pos() {
  1386  					// Comment is after the identifier.
  1387  					continue
  1388  				}
  1389  
  1390  				lastCommentLine := safetoken.Line(pgf.Tok, comment.End())
  1391  				if lastCommentLine+1 == identLine {
  1392  					return comment
  1393  				}
  1394  			}
  1395  		default:
  1396  			return nil
  1397  		}
  1398  	}
  1399  	return nil
  1400  }
  1401  
  1402  // updatePkgName returns the updates to rename a pkgName in the import spec by
  1403  // only modifying the package name portion of the import declaration.
  1404  func (r *renamer) updatePkgName(pgf *ParsedGoFile, pkgName *types.PkgName) (diff.Edit, error) {
  1405  	// Modify ImportSpec syntax to add or remove the Name as needed.
  1406  	path, _ := astutil.PathEnclosingInterval(pgf.File, pkgName.Pos(), pkgName.Pos())
  1407  	if len(path) < 2 {
  1408  		return diff.Edit{}, fmt.Errorf("no path enclosing interval for %s", pkgName.Name())
  1409  	}
  1410  	spec, ok := path[1].(*ast.ImportSpec)
  1411  	if !ok {
  1412  		return diff.Edit{}, fmt.Errorf("failed to update PkgName for %s", pkgName.Name())
  1413  	}
  1414  
  1415  	newText := ""
  1416  	if pkgName.Imported().Name() != r.to {
  1417  		newText = r.to + " "
  1418  	}
  1419  
  1420  	// Replace the portion (possibly empty) of the spec before the path:
  1421  	//     local "path"      or      "path"
  1422  	//   ->      <-                -><-
  1423  	return posEdit(pgf.Tok, spec.Pos(), spec.Path.Pos(), newText)
  1424  }
  1425  
  1426  // parsePackageNameDecl is a convenience function that parses and
  1427  // returns the package name declaration of file fh, and reports
  1428  // whether the position ppos lies within it.
  1429  //
  1430  // Note: also used by references.
  1431  func parsePackageNameDecl(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, ppos protocol.Position) (*ParsedGoFile, bool, error) {
  1432  	pgf, err := snapshot.ParseGo(ctx, fh, ParseHeader)
  1433  	if err != nil {
  1434  		return nil, false, err
  1435  	}
  1436  	// Careful: because we used ParseHeader,
  1437  	// pgf.Pos(ppos) may be beyond EOF => (0, err).
  1438  	pos, _ := pgf.PositionPos(ppos)
  1439  	return pgf, pgf.File.Name.Pos() <= pos && pos <= pgf.File.Name.End(), nil
  1440  }
  1441  
  1442  // enclosingFile returns the CompiledGoFile of pkg that contains the specified position.
  1443  func enclosingFile(pkg *cache.Package, pos token.Pos) (*ParsedGoFile, bool) {
  1444  	for _, pgf := range pkg.CompiledGoFiles() {
  1445  		if pgf.File.Pos() <= pos && pos <= pgf.File.End() {
  1446  			return pgf, true
  1447  		}
  1448  	}
  1449  	return nil, false
  1450  }
  1451  
  1452  // posEdit returns an edit to replace the (start, end) range of tf with 'new'.
  1453  func posEdit(tf *token.File, start, end token.Pos, new string) (diff.Edit, error) {
  1454  	startOffset, endOffset, err := safetoken.Offsets(tf, start, end)
  1455  	if err != nil {
  1456  		return diff.Edit{}, err
  1457  	}
  1458  	return diff.Edit{Start: startOffset, End: endOffset, New: new}, nil
  1459  }