Skip to content

Reuse programs across edits to files with synthetic imports - #65104

Merged
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
jakebailey:reuse-bug
Nov 2, 2026
Merged

Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
jakebailey:reuse-bug

Conversation

@jakebailey

Copy link
Copy Markdown
Member

Since content mappers were added, ReuseProgram falls back to a full program build whenever the edited file needs a synthetic tslib or JSX runtime import. Every .tsx file in a project using the automatic JSX runtime has one, so each keystroke in such a file rebuilds the whole program in the language server.

A synthetic import's resolution doesn't depend on the file's contents, so the program can be reused when the edit leaves the imports unchanged. The synthetic nodes are parented to the old file, so they are recreated for the new one, and include reasons now refer to synthetic imports by kind so they stay valid in the reused program.

Since content mappers were added, ReuseProgram falls back to a full
program build whenever the edited file needs a synthetic tslib or JSX
runtime import. Every .tsx file in a project using the automatic JSX
runtime has one, so each keystroke in such a file rebuilds the whole
program in the language server.

A synthetic import's resolution doesn't depend on the file's contents,
so the program can be reused when the edit leaves the imports
unchanged. The synthetic nodes are parented to the old file, so they
are recreated for the new one, and include reasons now refer to
synthetic imports by kind so they stay valid in the reused program.

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.

Nice find!

@github-project-automation github-project-automation Bot moved this from Not started to Needs merge in PR Backlog Nov 2, 2026

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.

🟡 Changes recommended

The reuse check permits cloning after a virtual extension changes from .cts to .mts, retaining stale CommonJS metadata and require-mode tslib resolution instead of rebuilding for ESM.

1 open issue
What changed in this PR

This PR lets the language server reuse programs after edits that leave synthetic tslib and JSX runtime imports unchanged, avoiding full program rebuilds for common TSX edits.

Changes:

  • Allow reuse when synthetic imports match, recreating their nodes for the updated files.
  • Track synthetic imports by kind so file-inclusion reasons remain valid across reuse.
  • Add coverage for reuse, synthetic-node ownership, diagnostics, and changed JSX import sources.
File Description
tsc/​internal/​project/​project_test.go Tests reuse with unchanged synthetic imports and fallback when the JSX import source changes.
tsc/​internal/​compiler/​program.go Checks synthetic-import compatibility and recreates nodes during reuse.
tsc/​internal/​compiler/​fileloader.go Records synthetic-import kinds and extracts shared node creation.
tsc/​internal/​compiler/​fileInclude.go Resolves synthetic-import inclusion reasons through the current program.

Review effort: Balanced

Comment thread tsc/internal/compiler/program.go Resolved
A content mapper can switch a file's virtual extension between edits,
for example from .cts to .mts. The parse options stay the same, so the
program was reused with the file's old implied module format and the
resolutions made under it, such as a require-mode tslib import.

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.

🟢 Approval recommended

No active review issues block the changes enabling program reuse when synthetic imports remain unchanged.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@jakebailey
Jake Bailey (jakebailey) added this pull request to the merge queue Nov 2, 2026
Merged via the queue into microsoft:main with commit f71e70d Nov 2, 2026
34 checks passed
@jakebailey
Jake Bailey (jakebailey) deleted the reuse-bug branch November 2, 2026 19:32
@github-project-automation github-project-automation Bot moved this from Needs merge to Done in PR Backlog Nov 2, 2026
@jakebailey Jake Bailey (jakebailey) added the Domain: Performance Performance related label Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants