gopls/internal/regtest: fix goimports on windows when using vendoring
Add a test for goimports when using mod vendoring on windows, along with
a very subtle one-line fix.
Fixes golang/go#56291
Change-Id: I2e45f70fc6dfa32164d4664acad886ec811474b8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/498695
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/gopls/internal/regtest/misc/vendor_test.go b/gopls/internal/regtest/misc/vendor_test.go
index 4fcf106..efed16b 100644
--- a/gopls/internal/regtest/misc/vendor_test.go
+++ b/gopls/internal/regtest/misc/vendor_test.go
@@ -63,3 +63,41 @@
)
})
}
+
+func TestWindowsVendoring_Issue56291(t *testing.T) {
+ const src = `
+-- go.mod --
+module mod.com
+
+go 1.14
+
+require golang.org/x/hello v1.2.3
+-- go.sum --
+golang.org/x/hello v1.2.3 h1:EcMp5gSkIhaTkPXp8/3+VH+IFqTpk3ZbpOhqk0Ncmho=
+golang.org/x/hello v1.2.3/go.mod h1:WW7ER2MRNXWA6c8/4bDIek4Hc/+DofTrMaQQitGXcco=
+-- main.go --
+package main
+
+import "golang.org/x/hello/hi"
+
+func main() {
+ _ = hi.Goodbye
+}
+`
+ WithOptions(
+ Modes(Default),
+ ProxyFiles(basicProxy),
+ ).Run(t, src, func(t *testing.T, env *Env) {
+ env.OpenFile("main.go")
+ env.AfterChange(NoDiagnostics())
+ env.RunGoCommand("mod", "tidy")
+ env.RunGoCommand("mod", "vendor")
+ env.AfterChange(NoDiagnostics())
+ env.RegexpReplace("main.go", `import "golang.org/x/hello/hi"`, "")
+ env.AfterChange(
+ Diagnostics(env.AtRegexp("main.go", "hi.Goodbye")),
+ )
+ env.SaveBuffer("main.go")
+ env.AfterChange(NoDiagnostics())
+ })
+}
diff --git a/internal/imports/mod.go b/internal/imports/mod.go
index 1389d38..977d238 100644
--- a/internal/imports/mod.go
+++ b/internal/imports/mod.go
@@ -38,7 +38,7 @@
mains []*gocommand.ModuleJSON
mainByDir map[string]*gocommand.ModuleJSON
modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path...
- modsByDir []*gocommand.ModuleJSON // ...or Dir.
+ modsByDir []*gocommand.ModuleJSON // ...or number of path components in their Dir.
// moduleCacheCache stores information about the module cache.
moduleCacheCache *dirInfoCache
@@ -124,7 +124,7 @@
})
sort.Slice(r.modsByDir, func(i, j int) bool {
count := func(x int) int {
- return strings.Count(r.modsByDir[x].Dir, "/")
+ return strings.Count(r.modsByDir[x].Dir, string(filepath.Separator))
}
return count(j) < count(i) // descending order
})
@@ -328,6 +328,10 @@
// - in /vendor/ in -mod=vendor mode.
// - nested module? Dunno.
// Rumor has it that replace targets cannot contain other replace targets.
+ //
+ // Note that it is critical here that modsByDir is sorted to have deeper dirs
+ // first. This ensures that findModuleByDir finds the innermost module.
+ // See also golang/go#56291.
for _, m := range r.modsByDir {
if !strings.HasPrefix(dir, m.Dir) {
continue