Skip to content

feat(mockgen): add project generate mode#306

Open
YuheiTakagawa wants to merge 5 commits into
uber-go:mainfrom
YuheiTakagawa:feat/project-generate-mode
Open

feat(mockgen): add project generate mode#306
YuheiTakagawa wants to merge 5 commits into
uber-go:mainfrom
YuheiTakagawa:feat/project-generate-mode

Conversation

@YuheiTakagawa

@YuheiTakagawa YuheiTakagawa commented Jul 19, 2026

Copy link
Copy Markdown

Summary

This adds a project-level generate mode to mockgen:

mockgen -generate ./...

The new mode discovers existing //go:generate directives that invoke mockgen across the requested package patterns and runs the matching mockgen invocations in-process. This keeps the existing go:generate directives as the source of truth while avoiding the cost of spawning one mockgen process per directive.

The implementation currently supports:

  • direct mockgen ... directives
  • go run ... mockgen ... directives, including common go run flags before the mockgen package
  • file-local //go:generate -command ... aliases that resolve to mockgen
  • generate build-tag files via go list -tags=generate
  • internal and external test files, including GOPACKAGE expansion for package foo_test
  • source, package, archive, and model gob modes through the existing mockgen paths

It also shares package name resolution across all discovered targets and uses go/format plus deterministic import grouping to avoid per-target goimports environment setup while preserving existing generated output.

Motivation

Large repositories can have hundreds or thousands of //go:generate mockgen ... directives. Running them through:

go generate --run=mockgen ./...

spawns one mockgen process per directive. Each process repeats package/import resolution and related go command work.

This mode provides a faster path for repositories that already maintain mockgen directives in source files, without introducing a separate config file or requiring users to manually maintain lists of source files.

Performance data

On a large repository with 1133 existing source-mode mockgen directives, I measured the following:

Existing workflow

go generate --run=mockgen ./...
  • mockgen processes: 1133
  • generated destinations: 1133
  • missing destinations: 0
  • changed files vs existing generated mocks: 0
  • fresh copy elapsed: 518.162s
  • hot rerun elapsed: 406.284s
  • nested go commands from a previous instrumented run:
    • 3482 total
    • 2349 go list
    • 1133 go env

New workflow

mockgen -generate ./...
  • mockgen processes: 1
  • generated destinations: 1133
  • missing destinations: 0
  • changed files vs existing generated mocks: 0
  • fresh copy elapsed: 182.753s
  • hot rerun elapsed: 48.153s
  • nested go commands:
    • 55 total
    • 55 go list
    • 0 go env

This is approximately:

  • 2.8x faster on a fresh copied repository
  • 8.4x faster on a hot rerun

Compatibility

I also verified the existing go generate --run=mockgen ./... workflow on the same large repository after these changes:

  • all 1133 destinations were generated
  • no outputs were missing
  • changed files vs existing generated mocks: 0

Implementation notes

  • -generate is a new top-level mode and is mutually exclusive with the existing single-target modes.
  • Discovery uses go list -e -tags=generate -json=Dir,Name,GoFiles,TestGoFiles,XTestGoFiles.
  • Directives are parsed and expanded with the go generate variables used by this mode: GOFILE, GOLINE, GOPACKAGE, and DOLLAR. Other variables are resolved from the process environment.
  • Matching mockgen directives are converted into the same option paths used by the existing CLI.
  • Package name resolution is primed in batches to reduce repeated go list calls and avoid command-line length issues.
  • Existing output files are read before writing; if generated output is byte-for-byte identical, the file is left untouched.

Test plan

go test ./mockgen -run 'TestParseGenerateDirectiveRecognizesGoRunWithFlags|TestParseGenerateDirectiveRecognizesCommandAlias|TestDiscoverGenerateTargetsIncludesGenerateTagFiles|TestDiscoverGenerateTargetsIncludesExternalTestFiles' -count=1
go test ./mockgen ./mockgen/model
go test ./...

Additional manual validation:

  • Ran mockgen -generate ./... on a large repository with 1133 existing mockgen directives.
  • Verified all 1133 expected destinations exist.
  • Verified there were no missing outputs.
  • Verified generated files were byte-for-byte identical to existing generated mocks.
  • Verified nested go command count was reduced to 55 total / 55 go list / 0 go env.

@CLAassistant

CLAassistant commented Jul 19, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@YuheiTakagawa YuheiTakagawa changed the title Feat/project generate mode feat(mockgen): add project generate mode Jul 19, 2026
@YuheiTakagawa

Copy link
Copy Markdown
Author

Please check this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants