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

Commit b48cb66

Browse files
authoredFeb 22, 2020
Improve performance of mock generation (#397)
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.
1 parent 0188501 commit b48cb66

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed
 

‎mockgen/mockgen.go

+22-12
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,12 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
304304
}
305305
sort.Strings(sortedPaths)
306306

307+
packagesName := createPackageMap(sortedPaths)
308+
307309
g.packageMap = make(map[string]string, len(im))
308310
localNames := make(map[string]bool, len(im))
309311
for _, pth := range sortedPaths {
310-
base, ok := lookupPackageName(pth)
312+
base, ok := packagesName[pth]
311313
if !ok {
312314
base = sanitize(path.Base(pth))
313315
}
@@ -622,22 +624,30 @@ func (g *generator) Output() []byte {
622624
return src
623625
}
624626

625-
func lookupPackageName(importPath string) (string, bool) {
627+
// createPackageMap returns a map of import path to package name
628+
// for specified importPaths.
629+
func createPackageMap(importPaths []string) map[string]string {
626630
var pkg struct {
627-
Name string
631+
Name string
632+
ImportPath string
628633
}
634+
pkgMap := make(map[string]string)
629635
b := bytes.NewBuffer(nil)
630-
cmd := exec.Command("go", "list", "-json", importPath)
636+
args := []string{"list", "-json"}
637+
args = append(args, importPaths...)
638+
cmd := exec.Command("go", args...)
631639
cmd.Stdout = b
632-
err := cmd.Run()
633-
if err != nil {
634-
return "", false
635-
}
636-
err = json.Unmarshal(b.Bytes(), &pkg)
637-
if err != nil {
638-
return "", false
640+
cmd.Run()
641+
dec := json.NewDecoder(b)
642+
for dec.More() {
643+
err := dec.Decode(&pkg)
644+
if err != nil {
645+
log.Printf("failed to decode 'go list' output: %v", err)
646+
continue
647+
}
648+
pkgMap[pkg.ImportPath] = pkg.Name
639649
}
640-
return pkg.Name, true
650+
return pkgMap
641651
}
642652

643653
func printVersion() {

‎mockgen/mockgen_test.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,7 @@ func TestGetArgNames(t *testing.T) {
335335
}
336336
}
337337

338-
func Test_lookupPackageName(t *testing.T) {
339-
type args struct {
340-
importPath string
341-
}
338+
func Test_createPackageMap(t *testing.T) {
342339
tests := []struct {
343340
name string
344341
importPath string
@@ -350,14 +347,19 @@ func Test_lookupPackageName(t *testing.T) {
350347
{"modules", "rsc.io/quote/v3", "quote", true},
351348
{"fail", "this/should/not/work", "", false},
352349
}
350+
var importPaths []string
351+
for _, t := range tests {
352+
importPaths = append(importPaths, t.importPath)
353+
}
354+
packages := createPackageMap(importPaths)
353355
for _, tt := range tests {
354356
t.Run(tt.name, func(t *testing.T) {
355-
gotPackageName, gotOk := lookupPackageName(tt.importPath)
357+
gotPackageName, gotOk := packages[tt.importPath]
356358
if gotPackageName != tt.wantPackageName {
357-
t.Errorf("lookupPackageName() gotPackageName = %v, wantPackageName %v", gotPackageName, tt.wantPackageName)
359+
t.Errorf("createPackageMap() gotPackageName = %v, wantPackageName = %v", gotPackageName, tt.wantPackageName)
358360
}
359361
if gotOk != tt.wantOK {
360-
t.Errorf("lookupPackageName() gotOk = %v, wantOK %v", gotOk, tt.wantOK)
362+
t.Errorf("createPackageMap() gotOk = %v, wantOK = %v", gotOk, tt.wantOK)
361363
}
362364
})
363365
}

‎mockgen/parse.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,15 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
432432
// importsOfFile returns a map of package name to import path
433433
// of the imports in file.
434434
func importsOfFile(file *ast.File) (normalImports map[string]string, dotImports []string) {
435+
var importPaths []string
436+
for _, is := range file.Imports {
437+
if is.Name != nil {
438+
continue
439+
}
440+
importPath := is.Path.Value[1 : len(is.Path.Value)-1] // remove quotes
441+
importPaths = append(importPaths, importPath)
442+
}
443+
packagesName := createPackageMap(importPaths)
435444
normalImports = make(map[string]string)
436445
dotImports = make([]string, 0)
437446
for _, is := range file.Imports {
@@ -445,7 +454,7 @@ func importsOfFile(file *ast.File) (normalImports map[string]string, dotImports
445454
}
446455
pkgName = is.Name.Name
447456
} else {
448-
pkg, ok := lookupPackageName(importPath)
457+
pkg, ok := packagesName[importPath]
449458
if !ok {
450459
// Fallback to import path suffix. Note that this is uncertain.
451460
_, last := path.Split(importPath)

0 commit comments

Comments
 (0)
This repository has been archived.