Skip to content

Make all the codegen we do incremental - #64331

Merged
Wesley Wigham (weswigham) merged 10 commits into
microsoft:mainfrom
weswigham:make-codegen-incremental
Sep 21, 2026
Merged

Wesley Wigham (weswigham) merged 10 commits into
microsoft:mainfrom
weswigham:make-codegen-incremental

Conversation

@weswigham

Copy link
Copy Markdown
Member

This PR adds incremental cache wrappers around all of the codegen we perform in the repo, which, experimentally, can cut up to 80% of the time off of some generate subtasks if the cached results are reusable. Very useful if you have an agent repeatedly running them just in case it modified a file that affects codegen.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Stringer can reuse stale output for package-wide changes, direct Go generation can lose formatter resolution, and duplicate broken test files remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Adds hash-based incremental caching and force-regeneration support across repository code generators.

Changes:

  • Introduces shared generated-file caching and generator utilities.
  • Wraps Go and TypeScript generators with cache-aware entry points.
  • Adds extensive code-generation integration tests.
File Description
tsc/​internal/​vfs/​vfsmatch/​vfsmatch.go Uses cached stringer wrapper.
tsc/​internal/​vfs/​vfs.go Uses cached moq wrapper.
tsc/​internal/​testutil/​projecttestutil/​projecttestutil.go Migrates mock generation.
tsc/​internal/​stringutil/​generate.go Consolidates Unicode formatting.
tsc/​internal/​stringutil/​_scripts/​generate-unicode-data.mts Caches Unicode outputs.
tsc/​internal/​project/​project.go Migrates stringer generation.
tsc/​internal/​ls/​autoimport/​export.go Migrates stringer generation.
tsc/​internal/​diagnostics/​diagnostics.go Uses cached diagnostics generator.
tsc/​internal/​core/​tristate.go Migrates stringer generation.
tsc/​internal/​core/​scriptkind.go Migrates stringer generation.
tsc/​internal/​core/​languagevariant.go Migrates stringer generation.
tsc/​internal/​core/​compileroptions.go Migrates stringer generation.
tsc/​internal/​checker/​types.go Migrates stringer generation.
tsc/​internal/​bundled/​bundled.go Uses cached bundle generator.
tsc/​internal/​ast/​kind_generated.go Updates generated directive.
tools/​scripts/​tsc/​tsconfig.json Extends shared generator config.
tools/​scripts/​tsc/​schema.ts Reuses shared repository root.
tools/​scripts/​tsc/​generate.ts Propagates forced regeneration.
tools/​scripts/​tsc/​generate-ts-ast.ts Caches TypeScript AST outputs.
tools/​scripts/​tsc/​generate-go-ast.ts Caches Go AST outputs.
tools/​scripts/​tsc/​generate-encoder.ts Caches protocol encoder outputs.
tools/​scripts/​generatedFile.test.mts Adds duplicate root-level tests.
tools/​scripts/​generatedFile.mts Adds duplicate cache implementation.
tools/​scripts/​gen/​utils.mts Adds shared generator utilities.
tools/​scripts/​gen/​tsconfig.json Configures generator type checking.
tools/​scripts/​gen/​generateStringer.mts Adds cached stringer wrapper.
tools/​scripts/​gen/​generateMoq.mts Adds cached moq wrapper.
tools/​scripts/​gen/​generateDiagnostics.mts Adds cached diagnostics generation.
tools/​scripts/​gen/​generatedFile.test.mts Tests incremental generation.
tools/​scripts/​gen/​generatedFile.mts Implements generated-output caching.
tools/​scripts/​gen/​generateBundled.mts Adds cached library bundling.
tools/​scripts/​gen/​generateAPI.mts Adds cached API generation.
packages/​typescript/​scripts/​generateSync.ts Caches sync API outputs.
packages/​typescript/​scripts/​generate.ts Coordinates package generators.
packages/​typescript/​package.json Uses unified package generator.
Herebyfile.mjs Adds force handling and cached tasks.
Files not reviewed (1)
  • tsc/internal/ast/kind_generated.go: Generated file

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread tools/scripts/gen/utils.mts
Comment thread tools/scripts/gen/generateStringer.mts Outdated
Comment thread tools/scripts/generatedFile.test.mts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The cache implementation validates inputs and outputs, handles failed or concurrent input changes safely, supports forced regeneration, and includes broad integration coverage.

Review effort: Balanced
Findings: None

Resolved since last review (3)
Files not reviewed (1)
  • tsc/internal/ast/kind_generated.go: Generated file

…asks - go:generate directives only for compat
@github-project-automation github-project-automation Bot moved this from Not started to Needs merge in PR Backlog Sep 21, 2026

@jakebailey Jake Bailey (jakebailey) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're doing a bunch of discussion off thread on Teams; I'm sort of leaning back to "maybe we should just move code generation into scripts and leave go generate for convenience" to avoid this getting too complicated and avoid the go generate overhead... Then just have hereby generate as "the thing to run" and it's incremental and that's that.

I do think that this is maybe a bit too complicated. But maybe it's whatever and we could just later future changes on it?

Comment thread CONTRIBUTING.md Outdated
Comment on lines +106 to +107
npx hereby generate # Regenerate compiler sources and bundled assets
npx hereby generate:all # Also regenerate AST, LSP, APIs, localization, and vendored files

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these might be out of date, if hereby generate now does everything for you, right?

Why would we want :all at all?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hereby generate does everything go generate would find, hereby generate:all does all generate-prefixed tasks, which is a handful more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think back compat really matters, is there any reason we wouldn't always run generate:all and therefore it should just be generate, and the Go code is relegated to generate:go?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can rename 'em if you'd like. Just left 'em like that because npx hereby generate just called out to go generate before.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think renaming is a good idea. When I introduced hereby generate, the only code we had to generate was go generate generated.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed the rename for ya.

Comment thread Herebyfile.mjs Outdated
@weswigham

Copy link
Copy Markdown
Member Author

We're doing a bunch of discussion off thread on Teams; I'm sort of leaning back to "maybe we should just move code generation into scripts and leave go generate for convenience" to avoid this getting too complicated and avoid the go generate overhead... Then just have hereby generate as "the thing to run" and it's incremental and that's that.

Yep - I just pushed those changes (and a merge commit fix) - I think I actually raced Andrew Branch (@andrewbranch) 's review there, so I'll re-request. I'm still collecting metrics, but it's promising thus far - cold generate calls are 5-10% faster, and warm ones are like 30%+ faster (which cascades into making validate faster, too). go generate must have pretty big overhead that we really didn't need.

Comment thread .github/workflows/ci.yml Outdated
@jakebailey

Copy link
Copy Markdown
Member

I think this is looking good, my only suggestion would be that the logging doesn't show much what's going on, like:

Generated codegen outputs.
Generated codegen outputs.
Generated codegen outputs.
Generated codegen outputs.
Generated codegen outputs.
Formatted 1 file.
Generated codegen outputs.
Generated codegen outputs.
Formatted 1 file.
Generated codegen outputs.
Generated codegen outputs.
Generated codegen outputs.
Generated codegen outputs.
Formatted 1 file.
Generated codegen outputs.
Generated codegen outputs.
Formatted 1 file.
Generated codegen outputs.
Generated codegen outputs.
Formatted 2 files.
Generated Unicode tables.
Formatted 1 file.

Compared to go generate listing packages, or otherwise things showing the commands being run (which herebyfile tries to do as much as possible).

@weswigham

Copy link
Copy Markdown
Member Author

That's pretty fair - the logging got simplified as I merged helpers from the first version and it got a wee bit too simple.

@weswigham

Copy link
Copy Markdown
Member Author

Jake Bailey (@jakebailey) There ya go, output of the cache layer's a bit more verbose.

Comment thread tools/scripts/gen/cache.mts Outdated
Comment thread Herebyfile.mjs Outdated
Comment thread tools/scripts/gen/cache.mts Outdated
@weswigham
Wesley Wigham (weswigham) added this pull request to the merge queue Sep 21, 2026
Merged via the queue into microsoft:main with commit 1ac2d5a Sep 21, 2026
28 checks passed
@weswigham
Wesley Wigham (weswigham) deleted the make-codegen-incremental branch September 21, 2026 22:36
@github-project-automation github-project-automation Bot moved this from Needs merge to Done in PR Backlog Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants