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
This commit is contained in:
Cody Oss 2020-01-20 12:21:39 -07:00 коммит произвёл GitHub
Родитель f165686a09
Коммит 3dcdcb6994
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 94 добавлений и 12 удалений

5
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

6
go.sum
Просмотреть файл

@ -2,6 +2,12 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
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=

Просмотреть файл

@ -6,7 +6,7 @@ package greeter
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 @@ func (m *MockInputMaker) EXPECT() *MockInputMakerMockRecorder {
}
// 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
}

Просмотреть файл

@ -6,7 +6,7 @@ package mock_source
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 @@ func (m *MockS) EXPECT() *MockSMockRecorder {
}
// 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)
}

Просмотреть файл

@ -20,6 +20,7 @@ package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"go/build"
@ -29,6 +30,7 @@ import (
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"sort"
@ -287,7 +289,10 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
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 @@ func (g *generator) Output() []byte {
}
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
}

Просмотреть файл

@ -334,3 +334,31 @@ func TestGetArgNames(t *testing.T) {
})
}
}
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)
}
})
}
}

Просмотреть файл

@ -453,15 +453,15 @@ func importsOfFile(file *ast.File) (normalImports map[string]string, dotImports
}
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
}
}

Просмотреть файл

@ -11,7 +11,7 @@ import (
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 @@ func (mr *MockIndexMockRecorder) EllipOnly(arg0 ...interface{}) *gomock.Call {
}
// 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)
}

22
tools.go Normal file
Просмотреть файл

@ -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"
)