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

Commit

Permalink
avoid using packages.Load
Browse files Browse the repository at this point in the history
fixed linting issues

Add tests

unexport error

making it Windows compatible
  • Loading branch information
linzhp committed Apr 8, 2020
1 parent 6d816de commit d4ca972
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 22 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module github.com/golang/mock

require (
golang.org/x/tools v0.0.0-20190425150028-36563e24a262
golang.org/x/mod v0.2.0
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
rsc.io/quote/v3 v3.1.0
)

Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJV
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/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
Expand Down
57 changes: 38 additions & 19 deletions mockgen/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import (
"go/token"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/golang/mock/mockgen/model"
"golang.org/x/tools/go/packages"
"golang.org/x/mod/modfile"
)

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

packageImport, err := parsePackageImport(source, srcDir)
packageImport, err := parsePackageImport(srcDir)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -604,31 +605,49 @@ func packageNameOfDir(srcDir string) (string, error) {
return "", fmt.Errorf("go source file not found %s", srcDir)
}

packageImport, err := parsePackageImport(goFilePath, srcDir)
packageImport, err := parsePackageImport(srcDir)
if err != nil {
return "", err
}
return packageImport, nil
}

var errOutsideGoPath = errors.New("Source directory is outside GOPATH")

// parseImportPackage get package import path via source file
func parsePackageImport(source, srcDir string) (string, error) {
cfg := &packages.Config{
Mode: packages.NeedName,
Tests: true,
Dir: srcDir,
// an alternative implementation is to use:
// cfg := &packages.Config{Mode: packages.NeedName, Tests: true, Dir: srcDir}
// pkgs, err := packages.Load(cfg, "file="+source)
// However, it will call "go list" and slow down the performance
func parsePackageImport(srcDir string) (string, error) {
moduleMode := os.Getenv("GO111MODULE")
// trying to find the module
if moduleMode != "off" {
currentDir := srcDir
for {
dat, err := ioutil.ReadFile(filepath.Join(currentDir, "go.mod"))
if os.IsNotExist(err) {
if currentDir == filepath.Dir(currentDir) {
// at the root
break
}
currentDir = filepath.Dir(currentDir)
continue
} else if err != nil {
return "", err
}
modulePath := modfile.ModulePath(dat)
return filepath.ToSlash(filepath.Join(modulePath, strings.TrimPrefix(srcDir, currentDir))), nil
}
}
pkgs, err := packages.Load(cfg, "file="+source)
if err != nil {
return "", err
// fall back to GOPATH mode
goPath := os.Getenv("GOPATH")
if goPath == "" {
return "", fmt.Errorf("GOPATH is not set")
}
if packages.PrintErrors(pkgs) > 0 || len(pkgs) == 0 {
return "", errors.New("loading package failed")
sourceRoot := filepath.Join(goPath, "src") + string(os.PathSeparator)
if !strings.HasPrefix(srcDir, sourceRoot) {
return "", errOutsideGoPath
}

packageImport := pkgs[0].PkgPath

// It is illegal to import a _test package.
packageImport = strings.TrimSuffix(packageImport, "_test")
return packageImport, nil
return filepath.ToSlash(strings.TrimPrefix(srcDir, sourceRoot)), nil
}
69 changes: 69 additions & 0 deletions mockgen/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"os"
"path/filepath"
"testing"
)

Expand Down Expand Up @@ -113,3 +116,69 @@ func Benchmark_parseFile(b *testing.B) {
sourceMode(source)
}
}

func TestParsePackageImport(t *testing.T) {
for _, testCase := range []struct {
name string
envs map[string]string
dir string
pkgPath string
err error
}{
{
name: "go mod default",
envs: map[string]string{"GO111MODULE": ""},
dir: "testdata/gomod/bar",
pkgPath: "github.com/golang/foo/bar",
},
{
name: "go mod off",
envs: map[string]string{"GO111MODULE": "off", "GOPATH": "testdata/gopath"},
dir: "testdata/gopath/src/example.com/foo",
pkgPath: "example.com/foo",
},
{
name: "outside GOPATH",
envs: map[string]string{"GO111MODULE": "off", "GOPATH": "testdata/gopath"},
dir: "testdata",
err: errOutsideGoPath,
},
} {
t.Run(testCase.name, func(t *testing.T) {
for key, value := range testCase.envs {
os.Setenv(key, value)
}
pkgPath, err := parsePackageImport(filepath.Clean(testCase.dir))
if err != testCase.err {
t.Errorf("expect %v, got %v", testCase.err, err)
}
if pkgPath != testCase.pkgPath {
t.Errorf("expect %s, got %s", testCase.pkgPath, pkgPath)
}
})
}
}

func TestParsePackageImport_FallbackGoPath(t *testing.T) {
goPath, err := ioutil.TempDir("", "gopath")
if err != nil {
t.Error(err)
}
defer func() {
if err = os.RemoveAll(goPath); err != nil {
t.Error(err)
}
}()
srcDir := filepath.Join(goPath, "src/example.com/foo")
err = os.MkdirAll(srcDir, 0755)
if err != nil {
t.Error(err)
}
os.Setenv("GOPATH", goPath)
os.Setenv("GO111MODULE", "on")
pkgPath, err := parsePackageImport(srcDir)
expected := "example.com/foo"
if pkgPath != expected {
t.Errorf("expect %s, got %s", expected, pkgPath)
}
}
1 change: 1 addition & 0 deletions mockgen/testdata/gomod/bar/bar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package bar
1 change: 1 addition & 0 deletions mockgen/testdata/gomod/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module github.com/golang/foo

0 comments on commit d4ca972

Please sign in to comment.