Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 2dcfc60

Browse files
committed
avoid using packages.Load
fixed linting issues Add tests unexport error making it Windows compatible
1 parent ccaa079 commit 2dcfc60

File tree

6 files changed

+122
-23
lines changed

6 files changed

+122
-23
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module github.com/golang/mock
22

33
require (
4-
golang.org/x/tools v0.0.0-20190425150028-36563e24a262
4+
golang.org/x/mod v0.2.0
5+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
56
rsc.io/quote/v3 v3.1.0
67
)
78

go.sum

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2-
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
2+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
3+
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
4+
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
5+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
6+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
37
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
48
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
9+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
510
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
611
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
712
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
8-
golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg=
9-
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
13+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
14+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
15+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
16+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
17+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1018
rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
1119
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
1220
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=

mockgen/parse.go

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import (
2626
"go/token"
2727
"io/ioutil"
2828
"log"
29+
"os"
2930
"path"
3031
"path/filepath"
3132
"strconv"
3233
"strings"
3334

3435
"github.com/golang/mock/mockgen/model"
35-
"golang.org/x/tools/go/packages"
36+
"golang.org/x/mod/modfile"
3637
)
3738

3839
var (
@@ -49,7 +50,7 @@ func sourceMode(source string) (*model.Package, error) {
4950
return nil, fmt.Errorf("failed getting source directory: %v", err)
5051
}
5152

52-
packageImport, err := parsePackageImport(source, srcDir)
53+
packageImport, err := parsePackageImport(srcDir)
5354
if err != nil {
5455
return nil, err
5556
}
@@ -539,31 +540,49 @@ func packageNameOfDir(srcDir string) (string, error) {
539540
return "", fmt.Errorf("go source file not found %s", srcDir)
540541
}
541542

542-
packageImport, err := parsePackageImport(goFilePath, srcDir)
543+
packageImport, err := parsePackageImport(srcDir)
543544
if err != nil {
544545
return "", err
545546
}
546547
return packageImport, nil
547548
}
548549

550+
var errOutsideGoPath = errors.New("Source directory is outside GOPATH")
551+
549552
// parseImportPackage get package import path via source file
550-
func parsePackageImport(source, srcDir string) (string, error) {
551-
cfg := &packages.Config{
552-
Mode: packages.NeedName,
553-
Tests: true,
554-
Dir: srcDir,
553+
// an alternative implementation is to use:
554+
// cfg := &packages.Config{Mode: packages.NeedName, Tests: true, Dir: srcDir}
555+
// pkgs, err := packages.Load(cfg, "file="+source)
556+
// However, it will call "go list" and slow down the performance
557+
func parsePackageImport(srcDir string) (string, error) {
558+
moduleMode := os.Getenv("GO111MODULE")
559+
// trying to find the module
560+
if moduleMode != "off" {
561+
currentDir := srcDir
562+
for {
563+
dat, err := ioutil.ReadFile(filepath.Join(currentDir, "go.mod"))
564+
if os.IsNotExist(err) {
565+
if currentDir == filepath.Dir(currentDir) {
566+
// at the root
567+
break
568+
}
569+
currentDir = filepath.Dir(currentDir)
570+
continue
571+
} else if err != nil {
572+
return "", err
573+
}
574+
modulePath := modfile.ModulePath(dat)
575+
return filepath.ToSlash(filepath.Join(modulePath, strings.TrimPrefix(srcDir, currentDir))), nil
576+
}
555577
}
556-
pkgs, err := packages.Load(cfg, "file="+source)
557-
if err != nil {
558-
return "", err
578+
// fall back to GOPATH mode
579+
goPath := os.Getenv("GOPATH")
580+
if goPath == "" {
581+
return "", fmt.Errorf("GOPATH is not set")
559582
}
560-
if packages.PrintErrors(pkgs) > 0 || len(pkgs) == 0 {
561-
return "", errors.New("loading package failed")
583+
sourceRoot := filepath.Join(goPath, "src") + string(os.PathSeparator)
584+
if !strings.HasPrefix(srcDir, sourceRoot) {
585+
return "", errOutsideGoPath
562586
}
563-
564-
packageImport := pkgs[0].PkgPath
565-
566-
// It is illegal to import a _test package.
567-
packageImport = strings.TrimSuffix(packageImport, "_test")
568-
return packageImport, nil
587+
return filepath.ToSlash(strings.TrimPrefix(srcDir, sourceRoot)), nil
569588
}

mockgen/parse_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import (
44
"go/ast"
55
"go/parser"
66
"go/token"
7+
"io/ioutil"
8+
"os"
9+
"path/filepath"
710
"testing"
811
)
912

@@ -113,3 +116,69 @@ func Benchmark_parseFile(b *testing.B) {
113116
sourceMode(source)
114117
}
115118
}
119+
120+
func TestParsePackageImport(t *testing.T) {
121+
for _, testCase := range []struct {
122+
name string
123+
envs map[string]string
124+
dir string
125+
pkgPath string
126+
err error
127+
}{
128+
{
129+
name: "go mod default",
130+
envs: map[string]string{"GO111MODULE": ""},
131+
dir: "testdata/gomod/bar",
132+
pkgPath: "github.com/golang/foo/bar",
133+
},
134+
{
135+
name: "go mod off",
136+
envs: map[string]string{"GO111MODULE": "off", "GOPATH": "testdata/gopath"},
137+
dir: "testdata/gopath/src/example.com/foo",
138+
pkgPath: "example.com/foo",
139+
},
140+
{
141+
name: "outside GOPATH",
142+
envs: map[string]string{"GO111MODULE": "off", "GOPATH": "testdata/gopath"},
143+
dir: "testdata",
144+
err: errOutsideGoPath,
145+
},
146+
} {
147+
t.Run(testCase.name, func(t *testing.T) {
148+
for key, value := range testCase.envs {
149+
os.Setenv(key, value)
150+
}
151+
pkgPath, err := parsePackageImport(filepath.Clean(testCase.dir))
152+
if err != testCase.err {
153+
t.Errorf("expect %v, got %v", testCase.err, err)
154+
}
155+
if pkgPath != testCase.pkgPath {
156+
t.Errorf("expect %s, got %s", testCase.pkgPath, pkgPath)
157+
}
158+
})
159+
}
160+
}
161+
162+
func TestParsePackageImport_FallbackGoPath(t *testing.T) {
163+
goPath, err := ioutil.TempDir("", "gopath")
164+
if err != nil {
165+
t.Error(err)
166+
}
167+
defer func() {
168+
if err = os.RemoveAll(goPath); err != nil {
169+
t.Error(err)
170+
}
171+
}()
172+
srcDir := filepath.Join(goPath, "src/example.com/foo")
173+
err = os.MkdirAll(srcDir, 0755)
174+
if err != nil {
175+
t.Error(err)
176+
}
177+
os.Setenv("GOPATH", goPath)
178+
os.Setenv("GO111MODULE", "on")
179+
pkgPath, err := parsePackageImport(srcDir)
180+
expected := "example.com/foo"
181+
if pkgPath != expected {
182+
t.Errorf("expect %s, got %s", expected, pkgPath)
183+
}
184+
}

mockgen/testdata/gomod/bar/bar.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package bar

mockgen/testdata/gomod/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module github.com/golang/foo

0 commit comments

Comments
 (0)