Skip to content

Restore tsgo exit code for noEmit type errors#4407

Open
Copilot wants to merge 4 commits into
mainfrom
copilot/fix-exit-code-type-error
Open

Restore tsgo exit code for noEmit type errors#4407
Copilot wants to merge 4 commits into
mainfrom
copilot/fix-exit-code-type-error

Conversation

Copilot AI commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

tsgo --noEmit started returning process exit code 1 for type errors after the internal ExitStatus values changed. tsc and previous tsgo releases return 2 for the same diagnostic path.

Analysis

The exit code derives from the ExitStatus: DiagnosticsPresent_OutputsSkipped (exit 1) vs DiagnosticsPresent_OutputsGenerated (exit 2). The status logic in internal/execute/tsc/emit.go already mirrors tsc (emitSkipped && diagnostics -> OutputsSkipped, else OutputsGenerated), so the bug was the wrong EmitSkipped value. tsgo's per-file emitters set EmitSkipped = true for noEmit, but tsc's handleNoEmitOptions only treats a single-file noEmit as skipped; a whole-program noEmit reports emitSkipped: false.

Fix

Port handleNoEmitOptions into Program.Emit: short-circuit noEmit before the per-file emitters and return EmitSkipped: options.TargetSourceFile != nil (false for a whole-program emit, true for a single file). This restores DiagnosticsPresent_OutputsGenerated for tsgo --noEmit and converges the tsc/noEmit baselines with upstream.

The change is scoped to the non-incremental path that the reported scenario uses; the shared incremental path (also used by build mode, whose status is derived differently upstream) is left unchanged.

Regression coverage

Reverted the earlier cmd/tsgo exit-code mapping hack and its non-tsc test, and added a tsc command-line regression test (noEmit with type error).

Copilot AI and others added 2 commits June 23, 2026 07:18
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix incorrect exit code for type error starting from 7.0.0-dev.20250724.1 Restore tsgo exit code for type errors Jun 23, 2026
Copilot AI requested a review from jakebailey June 23, 2026 07:24
@jakebailey

Copy link
Copy Markdown
Member

@copilot this seems totally random and hacky and not at all related to what the old compiler did, and the test case is not good as it's not a tsc test

rethink this entirely

Port tsc's handleNoEmitOptions in Program.Emit: a whole-program noEmit is
not skipped (only a single-file emit is), so a program with diagnostics
reports DiagnosticsPresent_OutputsGenerated, matching tsc and the process
exit code 2 that older tsgo releases produced.

Revert the earlier cmd/tsgo exit-code mapping hack and its test; add a tsc
command-line regression test instead.

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>

Copilot AI commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot this seems totally random and hacky and not at all related to what the old compiler did, and the test case is not good as it's not a tsc test

rethink this entirely

Rethought in cc8ea69. The root cause is the EmitSkipped value, not the exit-code mapping: tsc's handleNoEmitOptions only treats a single-file noEmit as skipped, while a whole-program noEmit reports emitSkipped: false (so diagnostics give DiagnosticsPresent_OutputsGenerated). tsgo's per-file emitters were setting EmitSkipped = true for noEmit. I ported handleNoEmitOptions into Program.Emit, reverted the cmd/tsgo hack and its test, and added a tsc command-line test (noEmit with type error). The tsc/noEmit baselines now converge with upstream.

Copilot AI changed the title Restore tsgo exit code for type errors Restore tsgo exit code for noEmit type errors Jun 23, 2026
Comment on lines +143 to 153
ExitStatus:: DiagnosticsPresent_OutputsGenerated
Output::
a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'.

1 const a: number = "hello"
   ~


Found 1 error in a.ts:1


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.

@copilot Isn't this strange? What files were generated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's strange, but it matches tsc: no files are generated. DiagnosticsPresent_OutputsGenerated is just a misnomer here.

For a whole-program --noEmit, tsc's handleNoEmitOptions (with sourceFile === undefined) returns program.emitBuildInfo(...). In a non-incremental program there's no buildInfo path, so emitFiles writes nothing and emitBuildInfo bails out early without setting emitSkipped, which is initialized to false. So the result is emitSkipped: false with zero emitted files, and emitFilesAndReportErrorsAndGetExitStatus falls into the diagnostics.length > 0 branch -> DiagnosticsPresent_OutputsGenerated (exit code 2).

The corresponding upstream baseline shows the same thing: no *new* files, yet exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated (_submodules/TypeScript/tests/baselines/reference/tsc/noEmit/multiFile/semantic-errors.js:54). The single-file case is the only one tsc treats as skipped (emitSkippedWithNoDiagnostics), which is why the port returns EmitSkipped: options.TargetSourceFile != nil.

Copilot AI requested a review from jakebailey June 23, 2026 19:57
@jakebailey jakebailey marked this pull request as ready for review June 23, 2026 21:12
Copilot AI review requested due to automatic review settings June 23, 2026 21:12

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.

Pull request overview

Restores tsgo’s exit-code behavior for --noEmit runs with diagnostics by aligning Program.Emit’s EmitSkipped semantics with upstream tsc (whole-program noEmit should not count as “emit skipped”, preserving exit status DiagnosticsPresent_OutputsGenerated).

Changes:

  • Short-circuit Program.Emit for noEmit and set EmitSkipped based on whether a target source file was specified.
  • Add a command-line regression test scenario for --noEmit with a type error.
  • Update tsc baseline outputs (notably ExitStatus and trace emit spans) to match the corrected behavior.

Reviewed changes

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

Show a summary per file
File Description
internal/compiler/program.go Implements noEmit short-circuit in Program.Emit, setting EmitSkipped to match tsc’s single-file vs whole-program behavior.
internal/execute/tsctests/tsc_test.go Adds a new command-line test case covering --noEmit with a type error.
testdata/baselines/reference/tsc/commandLine/noEmit-with-type-error.js New baseline validating exit status DiagnosticsPresent_OutputsGenerated for tsgo --noEmit index.ts with a type error.
testdata/baselines/reference/tsc/noEmit/syntax-errors.js Updates expected ExitStatus for --noEmit syntax-error scenarios to DiagnosticsPresent_OutputsGenerated.
testdata/baselines/reference/tsc/noEmit/semantic-errors.js Updates expected ExitStatus for --noEmit semantic-error scenarios to DiagnosticsPresent_OutputsGenerated.
testdata/baselines/reference/tsc/noEmit/dts-errors.js Updates expected ExitStatus for --noEmit declaration-related error scenarios to DiagnosticsPresent_OutputsGenerated.
testdata/baselines/reference/tsc/generateTrace/generateTrace-with-multiple-files-and-complex-types.js Updates expected ExitStatus and trace output to reflect the corrected noEmit/emit-skipped behavior.
testdata/baselines/reference/tsc/generateTrace/generateTrace-generates-types-file.js Updates trace output to reflect the corrected noEmit/emit-skipped behavior.

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.

Exit code for type error is incorrect starting from 7.0.0-dev.20250724.1

3 participants