internal/imports: don't prefix stdlib package with std/
When running in GOROOT/src, `go list -m all` shows the std package (or
cmd package) as the main module. This confuses goimports into adding
std/ or cmd/ at the beginning of import paths. Skip canonicalization for
paths under GOROOT.
Fixes golang/go#31814
Change-Id: Iff5cc7e2a2053e4cc87c1a579a4c47d856cd0a2e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/195063
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/imports/fix_test.go b/internal/imports/fix_test.go
index 610b9d5..8132954 100644
--- a/internal/imports/fix_test.go
+++ b/internal/imports/fix_test.go
@@ -7,6 +7,7 @@
import (
"flag"
"fmt"
+ "go/build"
"path/filepath"
"runtime"
"strings"
@@ -1538,6 +1539,39 @@
}
}
+// https://golang.org/issue/31814
+func TestStdlibNotPrefixed(t *testing.T) {
+ const input = `package p
+var _ = bytes.Buffer
+`
+ const want = `package p
+
+import "bytes"
+
+var _ = bytes.Buffer
+`
+ // Force a scan of the stdlib.
+ savedStdlib := stdlib
+ defer func() { stdlib = savedStdlib }()
+ stdlib = map[string]map[string]bool{}
+
+ testConfig{
+ module: packagestest.Module{
+ Name: "ignored.com",
+ },
+ }.test(t, func(t *goimportTest) {
+ // Run in GOROOT/src so that the std module shows up in go list -m all.
+ t.env.WorkingDir = filepath.Join(t.env.GOROOT, "src")
+ got, err := t.processNonModule(filepath.Join(t.env.GOROOT, "src/x.go"), []byte(input), nil)
+ if err != nil {
+ t.Fatalf("Process() = %v", err)
+ }
+ if string(got) != want {
+ t.Errorf("Got:\n%s\nWant:\n%s", got, want)
+ }
+ })
+}
+
type testConfig struct {
gopathOnly bool
goPackagesIncompatible bool
@@ -1609,6 +1643,11 @@
},
exported: exported,
}
+ if it.env.GOROOT == "" {
+ // packagestest clears out GOROOT to work around https://golang.org/issue/32849,
+ // which isn't relevant here. Fill it back in so we can find the standard library.
+ it.env.GOROOT = build.Default.GOROOT
+ }
fn(it)
})
}
diff --git a/internal/imports/mod.go b/internal/imports/mod.go
index 551bae8..387799b 100644
--- a/internal/imports/mod.go
+++ b/internal/imports/mod.go
@@ -313,7 +313,7 @@
// The rest of this function canonicalizes the packages using the results
// of initializing the resolver from 'go list -m'.
- res, err := r.canonicalize(info.nonCanonicalImportPath, info.dir, info.needsReplace)
+ res, err := r.canonicalize(root.Type, info.nonCanonicalImportPath, info.dir, info.needsReplace)
if err != nil {
return
}
@@ -335,7 +335,7 @@
continue
}
- res, err := r.canonicalize(info.nonCanonicalImportPath, info.dir, info.needsReplace)
+ res, err := r.canonicalize(gopathwalk.RootModuleCache, info.nonCanonicalImportPath, info.dir, info.needsReplace)
if err != nil {
continue
}
@@ -347,7 +347,15 @@
// canonicalize gets the result of canonicalizing the packages using the results
// of initializing the resolver from 'go list -m'.
-func (r *ModuleResolver) canonicalize(importPath, dir string, needsReplace bool) (res *pkg, err error) {
+func (r *ModuleResolver) canonicalize(rootType gopathwalk.RootType, importPath, dir string, needsReplace bool) (res *pkg, err error) {
+ // Packages in GOROOT are already canonical, regardless of the std/cmd modules.
+ if rootType == gopathwalk.RootGOROOT {
+ return &pkg{
+ importPathShort: importPath,
+ dir: dir,
+ }, nil
+ }
+
// Check if the directory is underneath a module that's in scope.
if mod := r.findModuleByDir(dir); mod != nil {
// It is. If dir is the target of a replace directive,