fix not resolving go module major versions (#385)
This change now makes use of go list to check for package names. This
tool is module aware and allows for better named imports.
To test this change I needed to also add a small package to our mod
file. To keep this import from disappearing from go.mod I made use
of the tools file strategy.
Note this change will change the import names in generated code. This
should not be a breaking change in user code.
Fixes #326
diff --git a/go.mod b/go.mod
index a675ec4..edfb6d4 100644
--- a/go.mod
+++ b/go.mod
@@ -1,5 +1,8 @@
module github.com/golang/mock
-require golang.org/x/tools v0.0.0-20190425150028-36563e24a262
+require (
+ golang.org/x/tools v0.0.0-20190425150028-36563e24a262
+ rsc.io/quote/v3 v3.1.0
+)
go 1.11
diff --git a/go.sum b/go.sum
index 9009852..21dbce5 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,12 @@
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/mockgen/internal/tests/custom_package_name/greeter/greeter_mock_test.go b/mockgen/internal/tests/custom_package_name/greeter/greeter_mock_test.go
index 0885f3d..41277d5 100644
--- a/mockgen/internal/tests/custom_package_name/greeter/greeter_mock_test.go
+++ b/mockgen/internal/tests/custom_package_name/greeter/greeter_mock_test.go
@@ -6,7 +6,7 @@
import (
gomock "github.com/golang/mock/gomock"
- v1 "github.com/golang/mock/mockgen/internal/tests/custom_package_name/client/v1"
+ client "github.com/golang/mock/mockgen/internal/tests/custom_package_name/client/v1"
reflect "reflect"
)
@@ -34,10 +34,10 @@
}
// MakeInput mocks base method
-func (m *MockInputMaker) MakeInput() v1.GreetInput {
+func (m *MockInputMaker) MakeInput() client.GreetInput {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MakeInput")
- ret0, _ := ret[0].(v1.GreetInput)
+ ret0, _ := ret[0].(client.GreetInput)
return ret0
}
diff --git a/mockgen/internal/tests/import_source/source_mock.go b/mockgen/internal/tests/import_source/source_mock.go
index d7c4769..847112d 100644
--- a/mockgen/internal/tests/import_source/source_mock.go
+++ b/mockgen/internal/tests/import_source/source_mock.go
@@ -6,7 +6,7 @@
import (
gomock "github.com/golang/mock/gomock"
- definition "github.com/golang/mock/mockgen/internal/tests/import_source/definition"
+ source "github.com/golang/mock/mockgen/internal/tests/import_source/definition"
reflect "reflect"
)
@@ -34,7 +34,7 @@
}
// F mocks base method
-func (m *MockS) F(arg0 definition.X) {
+func (m *MockS) F(arg0 source.X) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "F", arg0)
}
diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go
index b02aaf4..1f14aa7 100644
--- a/mockgen/mockgen.go
+++ b/mockgen/mockgen.go
@@ -20,6 +20,7 @@
import (
"bytes"
+ "encoding/json"
"flag"
"fmt"
"go/build"
@@ -29,6 +30,7 @@
"io/ioutil"
"log"
"os"
+ "os/exec"
"path"
"path/filepath"
"sort"
@@ -287,7 +289,10 @@
g.packageMap = make(map[string]string, len(im))
localNames := make(map[string]bool, len(im))
for _, pth := range sortedPaths {
- base := sanitize(path.Base(pth))
+ base, ok := lookupPackageName(pth)
+ if !ok {
+ base = sanitize(path.Base(pth))
+ }
// Local names for an imported package can usually be the basename of the import path.
// A couple of situations don't permit that, such as duplicate local names
@@ -598,3 +603,21 @@
}
return src
}
+
+func lookupPackageName(importPath string) (string, bool) {
+ var pkg struct {
+ Name string
+ }
+ b := bytes.NewBuffer(nil)
+ cmd := exec.Command("go", "list", "-json", importPath)
+ cmd.Stdout = b
+ err := cmd.Run()
+ if err != nil {
+ return "", false
+ }
+ err = json.Unmarshal(b.Bytes(), &pkg)
+ if err != nil {
+ return "", false
+ }
+ return pkg.Name, true
+}
diff --git a/mockgen/mockgen_test.go b/mockgen/mockgen_test.go
index 1c139d7..130d3cf 100644
--- a/mockgen/mockgen_test.go
+++ b/mockgen/mockgen_test.go
@@ -334,3 +334,31 @@
})
}
}
+
+func Test_lookupPackageName(t *testing.T) {
+ type args struct {
+ importPath string
+ }
+ tests := []struct {
+ name string
+ importPath string
+ wantPackageName string
+ wantOK bool
+ }{
+ {"golang package", "context", "context", true},
+ {"third party", "golang.org/x/tools/present", "present", true},
+ {"modules", "rsc.io/quote/v3", "quote", true},
+ {"fail", "this/should/not/work", "", false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotPackageName, gotOk := lookupPackageName(tt.importPath)
+ if gotPackageName != tt.wantPackageName {
+ t.Errorf("lookupPackageName() gotPackageName = %v, wantPackageName %v", gotPackageName, tt.wantPackageName)
+ }
+ if gotOk != tt.wantOK {
+ t.Errorf("lookupPackageName() gotOk = %v, wantOK %v", gotOk, tt.wantOK)
+ }
+ })
+ }
+}
diff --git a/mockgen/parse.go b/mockgen/parse.go
index e35d16f..2fdda65 100644
--- a/mockgen/parse.go
+++ b/mockgen/parse.go
@@ -453,15 +453,15 @@
}
pkgName = is.Name.Name
} else {
- pkg, err := build.Import(importPath, "", 0)
- if err != nil {
+ pkg, ok := lookupPackageName(importPath)
+ if !ok {
// Fallback to import path suffix. Note that this is uncertain.
_, last := path.Split(importPath)
// If the last path component has dots, the first dot-delimited
// field is used as the name.
pkgName = strings.SplitN(last, ".", 2)[0]
} else {
- pkgName = pkg.Name
+ pkgName = pkg
}
}
diff --git a/sample/mock_user/mock_user.go b/sample/mock_user/mock_user.go
index 4cf24bb..34fec0d 100644
--- a/sample/mock_user/mock_user.go
+++ b/sample/mock_user/mock_user.go
@@ -11,7 +11,7 @@
imp1 "github.com/golang/mock/sample/imp1"
imp2 "github.com/golang/mock/sample/imp2"
imp3 "github.com/golang/mock/sample/imp3"
- imp4 "github.com/golang/mock/sample/imp4"
+ imp_four "github.com/golang/mock/sample/imp4"
hash "hash"
template "html/template"
io "io"
@@ -115,7 +115,7 @@
}
// ForeignFour mocks base method
-func (m *MockIndex) ForeignFour(arg0 imp4.Imp4) {
+func (m *MockIndex) ForeignFour(arg0 imp_four.Imp4) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "ForeignFour", arg0)
}
diff --git a/tools.go b/tools.go
new file mode 100644
index 0000000..c1ea623
--- /dev/null
+++ b/tools.go
@@ -0,0 +1,22 @@
+// +build tools
+
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mock
+
+// These imports are included here so they don't disappear from go.mod file.
+import (
+ _ "rsc.io/quote/v3"
+)