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

Commit

Permalink
Improve performance of mock generation (#397)
Browse files Browse the repository at this point in the history
Optimizes resolving correct package name with `go list` command. Instead of calling go list for each import in file, now we do it for all imports in one call.
  • Loading branch information
plakhotnii committed Feb 22, 2020
1 parent 0188501 commit b48cb66
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 20 deletions.
34 changes: 22 additions & 12 deletions mockgen/mockgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,12 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
}
sort.Strings(sortedPaths)

packagesName := createPackageMap(sortedPaths)

g.packageMap = make(map[string]string, len(im))
localNames := make(map[string]bool, len(im))
for _, pth := range sortedPaths {
base, ok := lookupPackageName(pth)
base, ok := packagesName[pth]
if !ok {
base = sanitize(path.Base(pth))
}
Expand Down Expand Up @@ -622,22 +624,30 @@ func (g *generator) Output() []byte {
return src
}

func lookupPackageName(importPath string) (string, bool) {
// createPackageMap returns a map of import path to package name
// for specified importPaths.
func createPackageMap(importPaths []string) map[string]string {
var pkg struct {
Name string
Name string
ImportPath string
}
pkgMap := make(map[string]string)
b := bytes.NewBuffer(nil)
cmd := exec.Command("go", "list", "-json", importPath)
args := []string{"list", "-json"}
args = append(args, importPaths...)
cmd := exec.Command("go", args...)
cmd.Stdout = b
err := cmd.Run()
if err != nil {
return "", false
}
err = json.Unmarshal(b.Bytes(), &pkg)
if err != nil {
return "", false
cmd.Run()
dec := json.NewDecoder(b)
for dec.More() {
err := dec.Decode(&pkg)
if err != nil {
log.Printf("failed to decode 'go list' output: %v", err)
continue
}
pkgMap[pkg.ImportPath] = pkg.Name
}
return pkg.Name, true
return pkgMap
}

func printVersion() {
Expand Down
16 changes: 9 additions & 7 deletions mockgen/mockgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,7 @@ func TestGetArgNames(t *testing.T) {
}
}

func Test_lookupPackageName(t *testing.T) {
type args struct {
importPath string
}
func Test_createPackageMap(t *testing.T) {
tests := []struct {
name string
importPath string
Expand All @@ -350,14 +347,19 @@ func Test_lookupPackageName(t *testing.T) {
{"modules", "rsc.io/quote/v3", "quote", true},
{"fail", "this/should/not/work", "", false},
}
var importPaths []string
for _, t := range tests {
importPaths = append(importPaths, t.importPath)
}
packages := createPackageMap(importPaths)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotPackageName, gotOk := lookupPackageName(tt.importPath)
gotPackageName, gotOk := packages[tt.importPath]
if gotPackageName != tt.wantPackageName {
t.Errorf("lookupPackageName() gotPackageName = %v, wantPackageName %v", gotPackageName, tt.wantPackageName)
t.Errorf("createPackageMap() gotPackageName = %v, wantPackageName = %v", gotPackageName, tt.wantPackageName)
}
if gotOk != tt.wantOK {
t.Errorf("lookupPackageName() gotOk = %v, wantOK %v", gotOk, tt.wantOK)
t.Errorf("createPackageMap() gotOk = %v, wantOK = %v", gotOk, tt.wantOK)
}
})
}
Expand Down
11 changes: 10 additions & 1 deletion mockgen/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,15 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
// importsOfFile returns a map of package name to import path
// of the imports in file.
func importsOfFile(file *ast.File) (normalImports map[string]string, dotImports []string) {
var importPaths []string
for _, is := range file.Imports {
if is.Name != nil {
continue
}
importPath := is.Path.Value[1 : len(is.Path.Value)-1] // remove quotes
importPaths = append(importPaths, importPath)
}
packagesName := createPackageMap(importPaths)
normalImports = make(map[string]string)
dotImports = make([]string, 0)
for _, is := range file.Imports {
Expand All @@ -445,7 +454,7 @@ func importsOfFile(file *ast.File) (normalImports map[string]string, dotImports
}
pkgName = is.Name.Name
} else {
pkg, ok := lookupPackageName(importPath)
pkg, ok := packagesName[importPath]
if !ok {
// Fallback to import path suffix. Note that this is uncertain.
_, last := path.Split(importPath)
Expand Down

0 comments on commit b48cb66

Please sign in to comment.