Skip to content

Use tsgo to run type checks on client for watch#296215

Open
mjbvz wants to merge 3 commits intomicrosoft:mainfrom
mjbvz:dev/mjbvz/wonderful-piranha
Open

Use tsgo to run type checks on client for watch#296215
mjbvz wants to merge 3 commits intomicrosoft:mainfrom
mjbvz:dev/mjbvz/wonderful-piranha

Conversation

@mjbvz
Copy link
Copy Markdown
Collaborator

@mjbvz mjbvz commented Feb 19, 2026

This reduces the the first run time to get src transpiled and fully type checked to around 15seconds on my machine. Rechecking then takes around 5 seconds

This reduces the time to get `src` transpiled and fully type checked to around 15seconds on my machine
@mjbvz mjbvz requested a review from jrieken February 19, 2026 07:14
@mjbvz mjbvz self-assigned this Feb 19, 2026
Copilot AI review requested due to automatic review settings February 19, 2026 07:14
"allowJs": true,
"resolveJsonModule": true,
"isolatedModules": false,
"skipLibCheck": true,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

adding this temporarily to work around microsoft/tas-client#88

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the development watch pipeline to use tsgo for client type-checking (in esbuild-transpile mode) to reduce end-to-end watch latency.

Changes:

  • Enable skipLibCheck in src/tsconfig.json to reduce type-check overhead.
  • Add a new watchTypeCheckTask that runs tsgo --noEmit on changes.
  • Switch gulp watch-client (esbuild-transpile mode) to use the new tsgo-based watcher.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/tsconfig.json Enables skipLibCheck to reduce type-check cost.
build/lib/tsgo.ts Adjusts tsgo completion/error reporting output behavior.
build/lib/compilation.ts Introduces watchTypeCheckTask that debounces tsgo no-emit checks on file changes.
build/gulpfile.ts Wires watch-client (esbuild mode) to use watchTypeCheckTask instead of the old gulp-tsb watcher.

Comment on lines 39 to 41
const watchClientTask = useEsbuildTranspile
? task.define('watch-client', task.parallel(compilation.watchTask('out', false, 'src', { noEmit: true }), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask))
? task.define('watch-client', task.parallel(compilation.watchTypeCheckTask('src'), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask))
: task.define('watch-client', task.series(util.rimraf('out'), task.parallel(compilation.watchTask('out', false), compilation.watchApiProposalNamesTask, compilation.watchExtensionPointNamesTask, compilation.watchCodiconsTask)));
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

In esbuild-transpile mode, watch-client is now only running the tsgo typecheck watcher plus the metadata/codegen watchers. If nothing else in this task graph is generating/updating src/vs/monaco.d.ts (and related generated files) on change, that’s a regression from the previous compilation.watchTask(..., { noEmit: true }) behavior.

Either ensure watchTypeCheckTask handles Monaco d.ts generation (preferred), or add a dedicated generator watch task here.

Copilot uses AI. Check for mistakes.
Comment on lines +194 to +206
export function watchTypeCheckTask(src: string): task.StreamTask {
const theTask = () => {
const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json');
const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 });
const tsgoStream = watchInput.pipe(util.debounce(() => {
const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true });
const result = es.through();
stream.on('end', () => result.emit('end'));
stream.on('error', () => result.emit('end'));
return result;
}));
return tsgoStream;
};
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

watchTypeCheckTask replaces the old watchTask(..., { noEmit: true }) path, but it no longer runs MonacoGenerator in watch mode. That means src/vs/monaco.d.ts / standaloneEnums.ts won’t be auto-regenerated on relevant changes during gulp watch-client (esbuild mode), which previously happened via watchTask.

Consider invoking new MonacoGenerator(true).execute() (and keeping its file watchers alive) inside watchTypeCheckTask, or otherwise ensuring an equivalent Monaco d.ts generation step is still part of watch-client.

Copilot uses AI. Check for mistakes.
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.

@mjbvz I think this is good feedback

Comment on lines +194 to +206
export function watchTypeCheckTask(src: string): task.StreamTask {
const theTask = () => {
const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json');
const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 });
const tsgoStream = watchInput.pipe(util.debounce(() => {
const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true });
const result = es.through();
stream.on('end', () => result.emit('end'));
stream.on('error', () => result.emit('end'));
return result;
}));
return tsgoStream;
};
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.

@mjbvz I think this is good feedback

const projectPath = path.join(import.meta.dirname, '../../', src, 'tsconfig.json');
const watchInput = watch(`${src}/**`, { base: src, readDelay: 200 });
const tsgoStream = watchInput.pipe(util.debounce(() => {
const stream = createTsgoStream(projectPath, { taskName: 'watch-client-noEmit', noEmit: true });
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.

Is incremental or not? Like, will every file change cost 15 second (for type checking)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's closer to 5 seconds for updates. The initial 15 seconds is for the first build and is slower because all of the compile tasks are running at the same time

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I've now also enabled the --incremental option to speed up recompiles. In my testing, this reduces the recheck time to 2seconds. Hopefully longer term the TS team will improve their watcher so that we can use that and speed this up even further

const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
const timestampRegex = /^\[\d{2}:\d{2}:\d{2}\]\s*/;

export function spawnTsgo(projectPath: string, config: { taskName: string; noEmit?: boolean }, onComplete?: () => Promise<void> | void): Promise<void> {
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.

This should probably replace what I have added for CI/CD here

function runTsGoTypeCheck(): Promise<void> {

mjbvz and others added 2 commits February 19, 2026 09:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.

3 participants