cmd/goimports: support multiple comma-separated imports in -local flag

In cmd/goimports, allow for the -local flag to accept a comma-separated
list of import path prefixes. Also, update the imports package
accordingly to support this.

Fixes golang/go#19188

Change-Id: I083d584df8c3a77532f0f66e9c5d970960180e0d
Reviewed-on: https://go-review.googlesource.com/85397
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Nishanth Shanmugham 2017-12-23 03:05:04 -05:00 committed by Brad Fitzpatrick
parent 9f6d4ad827
commit 059bec968c
3 changed files with 73 additions and 23 deletions

View File

@ -47,7 +47,7 @@ var (
func init() { func init() {
flag.BoolVar(&options.AllErrors, "e", false, "report all errors (not just the first 10 on different lines)") flag.BoolVar(&options.AllErrors, "e", false, "report all errors (not just the first 10 on different lines)")
flag.StringVar(&imports.LocalPrefix, "local", "", "put imports beginning with this string after 3rd-party packages") flag.StringVar(&imports.LocalPrefix, "local", "", "put imports beginning with this string after 3rd-party packages; comma-separated list")
} }
func report(err error) { func report(err error) {

View File

@ -32,16 +32,26 @@ var (
testMu sync.RWMutex // guards globals reset by tests; used only if inTests testMu sync.RWMutex // guards globals reset by tests; used only if inTests
) )
// LocalPrefix, if set, instructs Process to sort import paths with the given // LocalPrefix is a comma-separated string of import path prefixes, which, if
// prefix into another group after 3rd-party packages. // set, instructs Process to sort the import paths with the given prefixes
// into another group after 3rd-party packages.
var LocalPrefix string var LocalPrefix string
func localPrefixes() []string {
if LocalPrefix != "" {
return strings.Split(LocalPrefix, ",")
}
return nil
}
// importToGroup is a list of functions which map from an import path to // importToGroup is a list of functions which map from an import path to
// a group number. // a group number.
var importToGroup = []func(importPath string) (num int, ok bool){ var importToGroup = []func(importPath string) (num int, ok bool){
func(importPath string) (num int, ok bool) { func(importPath string) (num int, ok bool) {
if LocalPrefix != "" && strings.HasPrefix(importPath, LocalPrefix) { for _, p := range localPrefixes() {
return 3, true if strings.HasPrefix(importPath, p) {
return 3, true
}
} }
return return
}, },

View File

@ -1420,19 +1420,21 @@ const Y = bar.X
// Tests that the LocalPrefix option causes imports // Tests that the LocalPrefix option causes imports
// to be added into a later group (num=3). // to be added into a later group (num=3).
func TestLocalPrefix(t *testing.T) { func TestLocalPrefix(t *testing.T) {
defer func(s string) { LocalPrefix = s }(LocalPrefix) tests := []struct {
LocalPrefix = "foo/" config testConfig
localPrefix string
testConfig{ src string
gopathFiles: map[string]string{ want string
"foo/bar/bar.go": "package bar \n const X = 1", }{
}, {
}.test(t, func(t *goimportTest) { config: testConfig{
buf, err := Process(t.gopath+"/src/test/t.go", []byte("package main \n const Y = bar.X \n const _ = runtime.GOOS"), &Options{}) gopathFiles: map[string]string{
if err != nil { "foo/bar/bar.go": "package bar \n const X = 1",
t.Fatal(err) },
} },
const want = `package main localPrefix: "foo/",
src: "package main \n const Y = bar.X \n const _ = runtime.GOOS",
want: `package main
import ( import (
"runtime" "runtime"
@ -1442,11 +1444,49 @@ import (
const Y = bar.X const Y = bar.X
const _ = runtime.GOOS const _ = runtime.GOOS
` `,
if string(buf) != want { },
t.Errorf("Got:\n%s\nWant:\n%s", buf, want) {
} config: testConfig{
}) gopathFiles: map[string]string{
"example.org/pkg/pkg.go": "package pkg \n const A = 1",
"foo/bar/bar.go": "package bar \n const B = 1",
"code.org/r/p/expproj/expproj.go": "package expproj \n const C = 1",
},
},
localPrefix: "example.org/pkg,foo/,code.org",
src: "package main \n const X = pkg.A \n const Y = bar.B \n const Z = expproj.C \n const _ = runtime.GOOS",
want: `package main
import (
"runtime"
"code.org/r/p/expproj"
"example.org/pkg"
"foo/bar"
)
const X = pkg.A
const Y = bar.B
const Z = expproj.C
const _ = runtime.GOOS
`,
},
}
for _, tt := range tests {
tt.config.test(t, func(t *goimportTest) {
defer func(s string) { LocalPrefix = s }(LocalPrefix)
LocalPrefix = tt.localPrefix
buf, err := Process(t.gopath+"/src/test/t.go", []byte(tt.src), &Options{})
if err != nil {
t.Fatal(err)
}
if string(buf) != tt.want {
t.Errorf("Got:\n%s\nWant:\n%s", buf, tt.want)
}
})
}
} }
// Tests that running goimport on files in GOROOT (for people hacking // Tests that running goimport on files in GOROOT (for people hacking