golang.org/x/tools/gopls@v0.15.3/internal/test/integration/misc/rename_test.go (about)

     1  // Copyright 2021 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 misc
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  
    12  	"golang.org/x/tools/gopls/internal/protocol"
    13  	"golang.org/x/tools/gopls/internal/test/compare"
    14  	. "golang.org/x/tools/gopls/internal/test/integration"
    15  )
    16  
    17  func TestPrepareRenameMainPackage(t *testing.T) {
    18  	const files = `
    19  -- go.mod --
    20  module mod.com
    21  
    22  go 1.18
    23  -- main.go --
    24  package main
    25  
    26  import (
    27  	"fmt"
    28  )
    29  
    30  func main() {
    31  	fmt.Println(1)
    32  }
    33  `
    34  	const wantErr = "can't rename package \"main\""
    35  	Run(t, files, func(t *testing.T, env *Env) {
    36  		env.OpenFile("main.go")
    37  		loc := env.RegexpSearch("main.go", `main`)
    38  		params := &protocol.PrepareRenameParams{
    39  			TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
    40  		}
    41  		_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
    42  		if err == nil {
    43  			t.Errorf("missing can't rename package main error from PrepareRename")
    44  		}
    45  
    46  		if err.Error() != wantErr {
    47  			t.Errorf("got %v, want %v", err.Error(), wantErr)
    48  		}
    49  	})
    50  }
    51  
    52  // Test case for golang/go#56227
    53  func TestRenameWithUnsafeSlice(t *testing.T) {
    54  	const files = `
    55  -- go.mod --
    56  module mod.com
    57  
    58  go 1.18
    59  -- p.go --
    60  package p
    61  
    62  import "unsafe"
    63  
    64  type T struct{}
    65  
    66  func (T) M() {}
    67  
    68  func _() {
    69  	x := [3]int{1, 2, 3}
    70  	ptr := unsafe.Pointer(&x)
    71  	_ = unsafe.Slice((*int)(ptr), 3)
    72  }
    73  `
    74  
    75  	Run(t, files, func(t *testing.T, env *Env) {
    76  		env.OpenFile("p.go")
    77  		env.Rename(env.RegexpSearch("p.go", "M"), "N") // must not panic
    78  	})
    79  }
    80  
    81  func TestPrepareRenameWithNoPackageDeclaration(t *testing.T) {
    82  	const files = `
    83  go 1.14
    84  -- lib/a.go --
    85  import "fmt"
    86  
    87  const A = 1
    88  
    89  func bar() {
    90  	fmt.Println("Bar")
    91  }
    92  
    93  -- main.go --
    94  package main
    95  
    96  import "fmt"
    97  
    98  func main() {
    99  	fmt.Println("Hello")
   100  }
   101  `
   102  	Run(t, files, func(t *testing.T, env *Env) {
   103  		env.OpenFile("lib/a.go")
   104  		err := env.Editor.Rename(env.Ctx, env.RegexpSearch("lib/a.go", "fmt"), "fmt1")
   105  		if got, want := fmt.Sprint(err), "no identifier found"; got != want {
   106  			t.Errorf("Rename: got error %v, want %v", got, want)
   107  		}
   108  	})
   109  }
   110  
   111  func TestPrepareRenameFailWithUnknownModule(t *testing.T) {
   112  	const files = `
   113  go 1.14
   114  -- lib/a.go --
   115  package lib
   116  
   117  const A = 1
   118  
   119  -- main.go --
   120  package main
   121  
   122  import (
   123  	"mod.com/lib"
   124  )
   125  
   126  func main() {
   127  	println("Hello")
   128  }
   129  `
   130  	const wantErr = "can't rename package: missing module information for package"
   131  	Run(t, files, func(t *testing.T, env *Env) {
   132  		loc := env.RegexpSearch("lib/a.go", "lib")
   133  		params := &protocol.PrepareRenameParams{
   134  			TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
   135  		}
   136  		_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
   137  		if err == nil || !strings.Contains(err.Error(), wantErr) {
   138  			t.Errorf("missing cannot rename packages with unknown module from PrepareRename")
   139  		}
   140  	})
   141  }
   142  
   143  // This test ensures that each import of a renamed package
   144  // is also renamed if it would otherwise create a conflict.
   145  func TestRenamePackageWithConflicts(t *testing.T) {
   146  	const files = `
   147  -- go.mod --
   148  module mod.com
   149  
   150  go 1.18
   151  -- lib/a.go --
   152  package lib
   153  
   154  const A = 1
   155  
   156  -- lib/nested/a.go --
   157  package nested
   158  
   159  const B = 1
   160  
   161  -- lib/x/a.go --
   162  package nested1
   163  
   164  const C = 1
   165  
   166  -- main.go --
   167  package main
   168  
   169  import (
   170  	"mod.com/lib"
   171  	"mod.com/lib/nested"
   172  	nested1 "mod.com/lib/x"
   173  )
   174  
   175  func main() {
   176  	println("Hello")
   177  }
   178  `
   179  	Run(t, files, func(t *testing.T, env *Env) {
   180  		env.OpenFile("lib/a.go")
   181  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
   182  
   183  		// Check if the new package name exists.
   184  		env.RegexpSearch("nested/a.go", "package nested")
   185  		env.RegexpSearch("main.go", `nested2 "mod.com/nested"`)
   186  		env.RegexpSearch("main.go", "mod.com/nested/nested")
   187  		env.RegexpSearch("main.go", `nested1 "mod.com/nested/x"`)
   188  	})
   189  }
   190  
   191  func TestRenamePackageWithAlias(t *testing.T) {
   192  	const files = `
   193  -- go.mod --
   194  module mod.com
   195  
   196  go 1.18
   197  -- lib/a.go --
   198  package lib
   199  
   200  const A = 1
   201  
   202  -- lib/nested/a.go --
   203  package nested
   204  
   205  const B = 1
   206  
   207  -- main.go --
   208  package main
   209  
   210  import (
   211  	"mod.com/lib"
   212  	lib1 "mod.com/lib/nested"
   213  )
   214  
   215  func main() {
   216  	println("Hello")
   217  }
   218  `
   219  	Run(t, files, func(t *testing.T, env *Env) {
   220  		env.OpenFile("lib/a.go")
   221  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
   222  
   223  		// Check if the new package name exists.
   224  		env.RegexpSearch("nested/a.go", "package nested")
   225  		env.RegexpSearch("main.go", "mod.com/nested")
   226  		env.RegexpSearch("main.go", `lib1 "mod.com/nested/nested"`)
   227  	})
   228  }
   229  
   230  func TestRenamePackageWithDifferentDirectoryPath(t *testing.T) {
   231  	const files = `
   232  -- go.mod --
   233  module mod.com
   234  
   235  go 1.18
   236  -- lib/a.go --
   237  package lib
   238  
   239  const A = 1
   240  
   241  -- lib/nested/a.go --
   242  package foo
   243  
   244  const B = 1
   245  
   246  -- main.go --
   247  package main
   248  
   249  import (
   250  	"mod.com/lib"
   251  	foo "mod.com/lib/nested"
   252  )
   253  
   254  func main() {
   255  	println("Hello")
   256  }
   257  `
   258  	Run(t, files, func(t *testing.T, env *Env) {
   259  		env.OpenFile("lib/a.go")
   260  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
   261  
   262  		// Check if the new package name exists.
   263  		env.RegexpSearch("nested/a.go", "package nested")
   264  		env.RegexpSearch("main.go", "mod.com/nested")
   265  		env.RegexpSearch("main.go", `foo "mod.com/nested/nested"`)
   266  	})
   267  }
   268  
   269  func TestRenamePackage(t *testing.T) {
   270  	const files = `
   271  -- go.mod --
   272  module mod.com
   273  
   274  go 1.18
   275  -- lib/a.go --
   276  package lib
   277  
   278  const A = 1
   279  
   280  -- lib/b.go --
   281  package lib
   282  
   283  const B = 1
   284  
   285  -- lib/nested/a.go --
   286  package nested
   287  
   288  const C = 1
   289  
   290  -- main.go --
   291  package main
   292  
   293  import (
   294  	"mod.com/lib"
   295  	"mod.com/lib/nested"
   296  )
   297  
   298  func main() {
   299  	println("Hello")
   300  }
   301  `
   302  	Run(t, files, func(t *testing.T, env *Env) {
   303  		env.OpenFile("lib/a.go")
   304  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
   305  
   306  		// Check if the new package name exists.
   307  		env.RegexpSearch("lib1/a.go", "package lib1")
   308  		env.RegexpSearch("lib1/b.go", "package lib1")
   309  		env.RegexpSearch("main.go", "mod.com/lib1")
   310  		env.RegexpSearch("main.go", "mod.com/lib1/nested")
   311  	})
   312  }
   313  
   314  // Test for golang/go#47564.
   315  func TestRenameInTestVariant(t *testing.T) {
   316  	const files = `
   317  -- go.mod --
   318  module mod.com
   319  
   320  go 1.12
   321  -- stringutil/stringutil.go --
   322  package stringutil
   323  
   324  func Identity(s string) string {
   325  	return s
   326  }
   327  -- stringutil/stringutil_test.go --
   328  package stringutil
   329  
   330  func TestIdentity(t *testing.T) {
   331  	if got := Identity("foo"); got != "foo" {
   332  		t.Errorf("bad")
   333  	}
   334  }
   335  -- main.go --
   336  package main
   337  
   338  import (
   339  	"fmt"
   340  
   341  	"mod.com/stringutil"
   342  )
   343  
   344  func main() {
   345  	fmt.Println(stringutil.Identity("hello world"))
   346  }
   347  `
   348  
   349  	Run(t, files, func(t *testing.T, env *Env) {
   350  		env.OpenFile("main.go")
   351  		env.Rename(env.RegexpSearch("main.go", `stringutil\.(Identity)`), "Identityx")
   352  		env.OpenFile("stringutil/stringutil_test.go")
   353  		text := env.BufferText("stringutil/stringutil_test.go")
   354  		if !strings.Contains(text, "Identityx") {
   355  			t.Errorf("stringutil/stringutil_test.go: missing expected token `Identityx` after rename:\n%s", text)
   356  		}
   357  	})
   358  }
   359  
   360  // This is a test that rename operation initiated by the editor function as expected.
   361  func TestRenameFileFromEditor(t *testing.T) {
   362  	const files = `
   363  -- go.mod --
   364  module mod.com
   365  
   366  go 1.16
   367  -- a/a.go --
   368  package a
   369  
   370  const X = 1
   371  -- a/x.go --
   372  package a
   373  
   374  const X = 2
   375  -- b/b.go --
   376  package b
   377  `
   378  
   379  	Run(t, files, func(t *testing.T, env *Env) {
   380  		// Rename files and verify that diagnostics are affected accordingly.
   381  
   382  		// Initially, we should have diagnostics on both X's, for their duplicate declaration.
   383  		env.OnceMet(
   384  			InitialWorkspaceLoad,
   385  			Diagnostics(env.AtRegexp("a/a.go", "X")),
   386  			Diagnostics(env.AtRegexp("a/x.go", "X")),
   387  		)
   388  
   389  		// Moving x.go should make the diagnostic go away.
   390  		env.RenameFile("a/x.go", "b/x.go")
   391  		env.AfterChange(
   392  			NoDiagnostics(ForFile("a/a.go")),               // no more duplicate declarations
   393  			Diagnostics(env.AtRegexp("b/b.go", "package")), // as package names mismatch
   394  		)
   395  
   396  		// Renaming should also work on open buffers.
   397  		env.OpenFile("b/x.go")
   398  
   399  		// Moving x.go back to a/ should cause the diagnostics to reappear.
   400  		env.RenameFile("b/x.go", "a/x.go")
   401  		env.AfterChange(
   402  			Diagnostics(env.AtRegexp("a/a.go", "X")),
   403  			Diagnostics(env.AtRegexp("a/x.go", "X")),
   404  		)
   405  
   406  		// Renaming the entire directory should move both the open and closed file.
   407  		env.RenameFile("a", "x")
   408  		env.AfterChange(
   409  			Diagnostics(env.AtRegexp("x/a.go", "X")),
   410  			Diagnostics(env.AtRegexp("x/x.go", "X")),
   411  		)
   412  
   413  		// As a sanity check, verify that x/x.go is open.
   414  		if text := env.BufferText("x/x.go"); text == "" {
   415  			t.Fatal("got empty buffer for x/x.go")
   416  		}
   417  	})
   418  }
   419  
   420  func TestRenamePackage_Tests(t *testing.T) {
   421  	const files = `
   422  -- go.mod --
   423  module mod.com
   424  
   425  go 1.18
   426  -- lib/a.go --
   427  package lib
   428  
   429  const A = 1
   430  
   431  -- lib/b.go --
   432  package lib
   433  
   434  const B = 1
   435  
   436  -- lib/a_test.go --
   437  package lib_test
   438  
   439  import (
   440  	"mod.com/lib"
   441  	"fmt
   442  )
   443  
   444  const C = 1
   445  
   446  -- lib/b_test.go --
   447  package lib
   448  
   449  import (
   450  	"fmt
   451  )
   452  
   453  const D = 1
   454  
   455  -- lib/nested/a.go --
   456  package nested
   457  
   458  const D = 1
   459  
   460  -- main.go --
   461  package main
   462  
   463  import (
   464  	"mod.com/lib"
   465  	"mod.com/lib/nested"
   466  )
   467  
   468  func main() {
   469  	println("Hello")
   470  }
   471  `
   472  	Run(t, files, func(t *testing.T, env *Env) {
   473  		env.OpenFile("lib/a.go")
   474  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
   475  
   476  		// Check if the new package name exists.
   477  		env.RegexpSearch("lib1/a.go", "package lib1")
   478  		env.RegexpSearch("lib1/b.go", "package lib1")
   479  		env.RegexpSearch("main.go", "mod.com/lib1")
   480  		env.RegexpSearch("main.go", "mod.com/lib1/nested")
   481  
   482  		// Check if the test package is renamed
   483  		env.RegexpSearch("lib1/a_test.go", "package lib1_test")
   484  		env.RegexpSearch("lib1/b_test.go", "package lib1")
   485  	})
   486  }
   487  
   488  func TestRenamePackage_NestedModule(t *testing.T) {
   489  	const files = `
   490  -- go.work --
   491  go 1.18
   492  use (
   493  	.
   494  	./foo/bar
   495  	./foo/baz
   496  )
   497  
   498  -- go.mod --
   499  module mod.com
   500  
   501  go 1.18
   502  
   503  require (
   504      mod.com/foo/bar v0.0.0
   505  )
   506  
   507  replace (
   508  	mod.com/foo/bar => ./foo/bar
   509  	mod.com/foo/baz => ./foo/baz
   510  )
   511  -- foo/foo.go --
   512  package foo
   513  
   514  import "fmt"
   515  
   516  func Bar() {
   517  	fmt.Println("In foo before renamed to foox.")
   518  }
   519  
   520  -- foo/bar/go.mod --
   521  module mod.com/foo/bar
   522  
   523  -- foo/bar/bar.go --
   524  package bar
   525  
   526  const Msg = "Hi from package bar"
   527  
   528  -- foo/baz/go.mod --
   529  module mod.com/foo/baz
   530  
   531  -- foo/baz/baz.go --
   532  package baz
   533  
   534  const Msg = "Hi from package baz"
   535  
   536  -- main.go --
   537  package main
   538  
   539  import (
   540  	"fmt"
   541  	"mod.com/foo/bar"
   542  	"mod.com/foo/baz"
   543  	"mod.com/foo"
   544  )
   545  
   546  func main() {
   547  	foo.Bar()
   548  	fmt.Println(bar.Msg)
   549  	fmt.Println(baz.Msg)
   550  }
   551  `
   552  	Run(t, files, func(t *testing.T, env *Env) {
   553  		env.OpenFile("foo/foo.go")
   554  		env.Rename(env.RegexpSearch("foo/foo.go", "foo"), "foox")
   555  
   556  		env.RegexpSearch("foox/foo.go", "package foox")
   557  		env.OpenFile("foox/bar/bar.go")
   558  		env.OpenFile("foox/bar/go.mod")
   559  
   560  		env.RegexpSearch("main.go", "mod.com/foo/bar")
   561  		env.RegexpSearch("main.go", "mod.com/foox")
   562  		env.RegexpSearch("main.go", "foox.Bar()")
   563  
   564  		env.RegexpSearch("go.mod", "./foox/bar")
   565  		env.RegexpSearch("go.mod", "./foox/baz")
   566  	})
   567  }
   568  
   569  func TestRenamePackage_DuplicateImport(t *testing.T) {
   570  	const files = `
   571  -- go.mod --
   572  module mod.com
   573  
   574  go 1.18
   575  -- lib/a.go --
   576  package lib
   577  
   578  const A = 1
   579  
   580  -- lib/nested/a.go --
   581  package nested
   582  
   583  const B = 1
   584  
   585  -- main.go --
   586  package main
   587  
   588  import (
   589  	"mod.com/lib"
   590  	lib1 "mod.com/lib"
   591  	lib2 "mod.com/lib/nested"
   592  )
   593  
   594  func main() {
   595  	println("Hello")
   596  }
   597  `
   598  	Run(t, files, func(t *testing.T, env *Env) {
   599  		env.OpenFile("lib/a.go")
   600  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
   601  
   602  		// Check if the new package name exists.
   603  		env.RegexpSearch("nested/a.go", "package nested")
   604  		env.RegexpSearch("main.go", "mod.com/nested")
   605  		env.RegexpSearch("main.go", `lib1 "mod.com/nested"`)
   606  		env.RegexpSearch("main.go", `lib2 "mod.com/nested/nested"`)
   607  	})
   608  }
   609  
   610  func TestRenamePackage_DuplicateBlankImport(t *testing.T) {
   611  	const files = `
   612  -- go.mod --
   613  module mod.com
   614  
   615  go 1.18
   616  -- lib/a.go --
   617  package lib
   618  
   619  const A = 1
   620  
   621  -- lib/nested/a.go --
   622  package nested
   623  
   624  const B = 1
   625  
   626  -- main.go --
   627  package main
   628  
   629  import (
   630  	"mod.com/lib"
   631  	_ "mod.com/lib"
   632  	lib1 "mod.com/lib/nested"
   633  )
   634  
   635  func main() {
   636  	println("Hello")
   637  }
   638  `
   639  	Run(t, files, func(t *testing.T, env *Env) {
   640  		env.OpenFile("lib/a.go")
   641  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "nested")
   642  
   643  		// Check if the new package name exists.
   644  		env.RegexpSearch("nested/a.go", "package nested")
   645  		env.RegexpSearch("main.go", "mod.com/nested")
   646  		env.RegexpSearch("main.go", `_ "mod.com/nested"`)
   647  		env.RegexpSearch("main.go", `lib1 "mod.com/nested/nested"`)
   648  	})
   649  }
   650  
   651  func TestRenamePackage_TestVariant(t *testing.T) {
   652  	const files = `
   653  -- go.mod --
   654  module mod.com
   655  
   656  go 1.12
   657  -- foo/foo.go --
   658  package foo
   659  
   660  const Foo = 42
   661  -- bar/bar.go --
   662  package bar
   663  
   664  import "mod.com/foo"
   665  
   666  const Bar = foo.Foo
   667  -- bar/bar_test.go --
   668  package bar
   669  
   670  import "mod.com/foo"
   671  
   672  const Baz = foo.Foo
   673  -- testdata/bar/bar.go --
   674  package bar
   675  
   676  import "mod.com/foox"
   677  
   678  const Bar = foox.Foo
   679  -- testdata/bar/bar_test.go --
   680  package bar
   681  
   682  import "mod.com/foox"
   683  
   684  const Baz = foox.Foo
   685  `
   686  	Run(t, files, func(t *testing.T, env *Env) {
   687  		env.OpenFile("foo/foo.go")
   688  		env.Rename(env.RegexpSearch("foo/foo.go", "package (foo)"), "foox")
   689  
   690  		checkTestdata(t, env)
   691  	})
   692  }
   693  
   694  func TestRenamePackage_IntermediateTestVariant(t *testing.T) {
   695  	// In this test set up, we have the following import edges:
   696  	//   bar_test -> baz -> foo -> bar
   697  	//   bar_test -> foo -> bar
   698  	//   bar_test -> bar
   699  	//
   700  	// As a consequence, bar_x_test.go is in the reverse closure of both
   701  	// `foo [bar.test]` and `baz [bar.test]`. This test confirms that we don't
   702  	// produce duplicate edits in this case.
   703  	const files = `
   704  -- go.mod --
   705  module foo.mod
   706  
   707  go 1.12
   708  -- foo/foo.go --
   709  package foo
   710  
   711  import "foo.mod/bar"
   712  
   713  const Foo = 42
   714  
   715  const _ = bar.Bar
   716  -- baz/baz.go --
   717  package baz
   718  
   719  import "foo.mod/foo"
   720  
   721  const Baz = foo.Foo
   722  -- bar/bar.go --
   723  package bar
   724  
   725  var Bar = 123
   726  -- bar/bar_test.go --
   727  package bar
   728  
   729  const _ = Bar
   730  -- bar/bar_x_test.go --
   731  package bar_test
   732  
   733  import (
   734  	"foo.mod/bar"
   735  	"foo.mod/baz"
   736  	"foo.mod/foo"
   737  )
   738  
   739  const _ = bar.Bar + baz.Baz + foo.Foo
   740  -- testdata/foox/foo.go --
   741  package foox
   742  
   743  import "foo.mod/bar"
   744  
   745  const Foo = 42
   746  
   747  const _ = bar.Bar
   748  -- testdata/baz/baz.go --
   749  package baz
   750  
   751  import "foo.mod/foox"
   752  
   753  const Baz = foox.Foo
   754  -- testdata/bar/bar_x_test.go --
   755  package bar_test
   756  
   757  import (
   758  	"foo.mod/bar"
   759  	"foo.mod/baz"
   760  	"foo.mod/foox"
   761  )
   762  
   763  const _ = bar.Bar + baz.Baz + foox.Foo
   764  `
   765  
   766  	Run(t, files, func(t *testing.T, env *Env) {
   767  		env.OpenFile("foo/foo.go")
   768  		env.Rename(env.RegexpSearch("foo/foo.go", "package (foo)"), "foox")
   769  
   770  		checkTestdata(t, env)
   771  	})
   772  }
   773  
   774  func TestRenamePackage_Nesting(t *testing.T) {
   775  	const files = `
   776  -- go.mod --
   777  module mod.com
   778  
   779  go 1.18
   780  -- lib/a.go --
   781  package lib
   782  
   783  import "mod.com/lib/nested"
   784  
   785  const A = 1 + nested.B
   786  -- lib/nested/a.go --
   787  package nested
   788  
   789  const B = 1
   790  -- other/other.go --
   791  package other
   792  
   793  import (
   794  	"mod.com/lib"
   795  	"mod.com/lib/nested"
   796  )
   797  
   798  const C = lib.A + nested.B
   799  -- testdata/libx/a.go --
   800  package libx
   801  
   802  import "mod.com/libx/nested"
   803  
   804  const A = 1 + nested.B
   805  -- testdata/other/other.go --
   806  package other
   807  
   808  import (
   809  	"mod.com/libx"
   810  	"mod.com/libx/nested"
   811  )
   812  
   813  const C = libx.A + nested.B
   814  `
   815  	Run(t, files, func(t *testing.T, env *Env) {
   816  		env.OpenFile("lib/a.go")
   817  		env.Rename(env.RegexpSearch("lib/a.go", "package (lib)"), "libx")
   818  
   819  		checkTestdata(t, env)
   820  	})
   821  }
   822  
   823  func TestRenamePackage_InvalidName(t *testing.T) {
   824  	const files = `
   825  -- go.mod --
   826  module mod.com
   827  
   828  go 1.18
   829  -- lib/a.go --
   830  package lib
   831  
   832  import "mod.com/lib/nested"
   833  
   834  const A = 1 + nested.B
   835  `
   836  
   837  	Run(t, files, func(t *testing.T, env *Env) {
   838  		env.OpenFile("lib/a.go")
   839  		loc := env.RegexpSearch("lib/a.go", "package (lib)")
   840  
   841  		for _, badName := range []string{"$$$", "lib_test"} {
   842  			if err := env.Editor.Rename(env.Ctx, loc, badName); err == nil {
   843  				t.Errorf("Rename(lib, libx) succeeded, want non-nil error")
   844  			}
   845  		}
   846  	})
   847  }
   848  
   849  func TestRenamePackage_InternalPackage(t *testing.T) {
   850  	const files = `
   851  -- go.mod --
   852  module mod.com
   853  
   854  go 1.18
   855  -- lib/a.go --
   856  package lib
   857  
   858  import (
   859  	"fmt"
   860  	"mod.com/lib/internal/x"
   861  )
   862  
   863  const A = 1
   864  
   865  func print() {
   866  	fmt.Println(x.B)
   867  }
   868  
   869  -- lib/internal/x/a.go --
   870  package x
   871  
   872  const B = 1
   873  
   874  -- main.go --
   875  package main
   876  
   877  import "mod.com/lib"
   878  
   879  func main() {
   880  	lib.print()
   881  }
   882  `
   883  	Run(t, files, func(t *testing.T, env *Env) {
   884  		env.OpenFile("lib/internal/x/a.go")
   885  		env.Rename(env.RegexpSearch("lib/internal/x/a.go", "x"), "utils")
   886  
   887  		// Check if the new package name exists.
   888  		env.RegexpSearch("lib/a.go", "mod.com/lib/internal/utils")
   889  		env.RegexpSearch("lib/a.go", "utils.B")
   890  
   891  		// Check if the test package is renamed
   892  		env.RegexpSearch("lib/internal/utils/a.go", "package utils")
   893  
   894  		env.OpenFile("lib/a.go")
   895  		env.Rename(env.RegexpSearch("lib/a.go", "lib"), "lib1")
   896  
   897  		// Check if the new package name exists.
   898  		env.RegexpSearch("lib1/a.go", "package lib1")
   899  		env.RegexpSearch("lib1/a.go", "mod.com/lib1/internal/utils")
   900  		env.RegexpSearch("main.go", `import "mod.com/lib1"`)
   901  		env.RegexpSearch("main.go", "lib1.print()")
   902  	})
   903  }
   904  
   905  // checkTestdata checks that current buffer contents match their corresponding
   906  // expected content in the testdata directory.
   907  func checkTestdata(t *testing.T, env *Env) {
   908  	t.Helper()
   909  	files := env.ListFiles("testdata")
   910  	if len(files) == 0 {
   911  		t.Fatal("no files in testdata directory")
   912  	}
   913  	for _, file := range files {
   914  		suffix := strings.TrimPrefix(file, "testdata/")
   915  		got := env.BufferText(suffix)
   916  		want := env.ReadWorkspaceFile(file)
   917  		if diff := compare.Text(want, got); diff != "" {
   918  			t.Errorf("Rename: unexpected buffer content for %s (-want +got):\n%s", suffix, diff)
   919  		}
   920  	}
   921  }