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

Commit b48cb66

Browse files
authored
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

Lines changed: 22 additions & 12 deletions
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

Lines changed: 9 additions & 7 deletions
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

Lines changed: 10 additions & 1 deletion
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy