diff --git a/internal/compiler/program.go b/internal/compiler/program.go index 35093fab681..a4bc6fca222 100644 --- a/internal/compiler/program.go +++ b/internal/compiler/program.go @@ -1631,6 +1631,11 @@ func (p *Program) Emit(ctx context.Context, options EmitOptions) *EmitResult { } if options.EmitOnly != EmitOnlyForcedDts { + if p.Options().NoEmit.IsTrue() { + // Mirror handleNoEmitOptions: a single-file noEmit is skipped, but a whole-program + // noEmit is not, so a program with diagnostics reports DiagnosticsPresent_OutputsGenerated. + return &EmitResult{EmitSkipped: options.TargetSourceFile != nil} + } result := HandleNoEmitOnError( ctx, p, diff --git a/internal/execute/tsctests/tsc_test.go b/internal/execute/tsctests/tsc_test.go index 46128bbb759..693184fcce0 100644 --- a/internal/execute/tsctests/tsc_test.go +++ b/internal/execute/tsctests/tsc_test.go @@ -118,6 +118,11 @@ func TestTscCommandline(t *testing.T) { files: FileMap{"/home/src/workspaces/project/first.ts": `export const Key = Symbol()`}, commandLineArgs: []string{"--lib", "es6 ", "first.ts"}, }, + { + subScenario: "noEmit with type error", + files: FileMap{"/home/src/workspaces/project/index.ts": `x = 5;`}, + commandLineArgs: []string{"--noEmit", "index.ts"}, + }, { subScenario: "option diagnostics are suppressed when there are syntactic errors", files: FileMap{"/home/src/workspaces/project/a.ts": `const x: = 1;`}, diff --git a/testdata/baselines/reference/tsc/commandLine/noEmit-with-type-error.js b/testdata/baselines/reference/tsc/commandLine/noEmit-with-type-error.js new file mode 100644 index 00000000000..fbe6848a262 --- /dev/null +++ b/testdata/baselines/reference/tsc/commandLine/noEmit-with-type-error.js @@ -0,0 +1,41 @@ +currentDirectory::/home/src/workspaces/project +useCaseSensitiveFileNames::true +Input:: +//// [/home/src/workspaces/project/index.ts] *new* +x = 5; + +tsgo --noEmit index.ts +ExitStatus:: DiagnosticsPresent_OutputsGenerated +Output:: +index.ts:1:1 - error TS2304: Cannot find name 'x'. + +1 x = 5; +  ~ + + +Found 1 error in index.ts:1 + +//// [/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts] *Lib* +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +interface SymbolConstructor { + (desc?: string | number): symbol; + for(name: string): symbol; + readonly toStringTag: symbol; +} +declare var Symbol: SymbolConstructor; +interface Symbol { + readonly [Symbol.toStringTag]: string; +} +declare const console: { log(msg: any): void; }; + diff --git a/testdata/baselines/reference/tsc/generateTrace/generateTrace-generates-types-file.js b/testdata/baselines/reference/tsc/generateTrace/generateTrace-generates-types-file.js index 7905bb21b6b..ac1c0aa7a47 100644 --- a/testdata/baselines/reference/tsc/generateTrace/generateTrace-generates-types-file.js +++ b/testdata/baselines/reference/tsc/generateTrace/generateTrace-generates-types-file.js @@ -77,9 +77,7 @@ declare const console: { log(msg: any): void; }; {"pid":1,"tid":2,"ph":"E","cat":"check","ts":18,"name":"checkSourceFile","args":{"checkerId":0,"path":"/home/src/workspaces/project/a.ts"}}, {"pid":1,"tid":1,"ph":"E","cat":"check","ts":19,"name":"checkSourceFiles"}, {"pid":1,"tid":1,"ph":"B","cat":"emit","ts":20,"name":"emit"}, -{"pid":1,"tid":354130385,"ph":"B","cat":"emit","ts":21,"name":"emit","args":{"path":"/home/src/workspaces/project/a.ts"}}, -{"pid":1,"tid":354130385,"ph":"E","cat":"emit","ts":22,"name":"emit","args":{"path":"/home/src/workspaces/project/a.ts"}}, -{"pid":1,"tid":1,"ph":"E","cat":"emit","ts":23,"name":"emit"} +{"pid":1,"tid":1,"ph":"E","cat":"emit","ts":21,"name":"emit"} ] //// [/home/src/workspaces/project/trace/types_0.json] *new* diff --git a/testdata/baselines/reference/tsc/generateTrace/generateTrace-with-multiple-files-and-complex-types.js b/testdata/baselines/reference/tsc/generateTrace/generateTrace-with-multiple-files-and-complex-types.js index d981e92cb2f..befa8be5368 100644 --- a/testdata/baselines/reference/tsc/generateTrace/generateTrace-with-multiple-files-and-complex-types.js +++ b/testdata/baselines/reference/tsc/generateTrace/generateTrace-with-multiple-files-and-complex-types.js @@ -20,7 +20,7 @@ export interface Container { export type Nullable = T | null | undefined; tsgo --generateTrace /home/src/workspaces/project/trace --singleThreaded -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: main.ts:2:74 - error TS2322: Type '(fn: (x: number) => U) => Container' is not assignable to type '(fn: (x: U) => U) => Container'. Types of parameters 'fn' and 'fn' are incompatible. @@ -104,11 +104,7 @@ declare const console: { log(msg: any): void; }; {"pid":1,"tid":2,"ph":"E","cat":"check","ts":24,"name":"checkSourceFile","args":{"checkerId":0,"path":"/home/src/workspaces/project/main.ts"}}, {"pid":1,"tid":1,"ph":"E","cat":"check","ts":25,"name":"checkSourceFiles"}, {"pid":1,"tid":1,"ph":"B","cat":"emit","ts":26,"name":"emit"}, -{"pid":1,"tid":100209852,"ph":"B","cat":"emit","ts":27,"name":"emit","args":{"path":"/home/src/workspaces/project/main.ts"}}, -{"pid":1,"tid":100209852,"ph":"E","cat":"emit","ts":28,"name":"emit","args":{"path":"/home/src/workspaces/project/main.ts"}}, -{"pid":1,"tid":553096334,"ph":"B","cat":"emit","ts":29,"name":"emit","args":{"path":"/home/src/workspaces/project/types.ts"}}, -{"pid":1,"tid":553096334,"ph":"E","cat":"emit","ts":30,"name":"emit","args":{"path":"/home/src/workspaces/project/types.ts"}}, -{"pid":1,"tid":1,"ph":"E","cat":"emit","ts":31,"name":"emit"} +{"pid":1,"tid":1,"ph":"E","cat":"emit","ts":27,"name":"emit"} ] //// [/home/src/workspaces/project/trace/types_0.json] *new* diff --git a/testdata/baselines/reference/tsc/noEmit/dts-errors.js b/testdata/baselines/reference/tsc/noEmit/dts-errors.js index 67254f6a2b2..299fdcb8dac 100644 --- a/testdata/baselines/reference/tsc/noEmit/dts-errors.js +++ b/testdata/baselines/reference/tsc/noEmit/dts-errors.js @@ -12,7 +12,7 @@ const a = class { private p = 10; }; } tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS4094: Property 'p' of exported anonymous class type may not be private or protected. @@ -55,7 +55,7 @@ declare const console: { log(msg: any): void; }; Edit [0]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS4094: Property 'p' of exported anonymous class type may not be private or protected. @@ -118,7 +118,7 @@ Edit [5]:: Introduce error const a = class { private p = 10; }; tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS4094: Property 'p' of exported anonymous class type may not be private or protected. @@ -164,7 +164,7 @@ const a = class { Edit [7]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS4094: Property 'p' of exported anonymous class type may not be private or protected. diff --git a/testdata/baselines/reference/tsc/noEmit/semantic-errors.js b/testdata/baselines/reference/tsc/noEmit/semantic-errors.js index 96ff47848c8..78f6e09630f 100644 --- a/testdata/baselines/reference/tsc/noEmit/semantic-errors.js +++ b/testdata/baselines/reference/tsc/noEmit/semantic-errors.js @@ -12,7 +12,7 @@ const a: number = "hello" } tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'. @@ -51,7 +51,7 @@ declare const console: { log(msg: any): void; }; Edit [0]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'. @@ -107,7 +107,7 @@ Edit [5]:: Introduce error const a: number = "hello" tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'. @@ -140,7 +140,7 @@ Found 1 error in a.ts:1 Edit [7]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'. diff --git a/testdata/baselines/reference/tsc/noEmit/syntax-errors.js b/testdata/baselines/reference/tsc/noEmit/syntax-errors.js index 5f1f5d6e7c4..8e28f48d7b3 100644 --- a/testdata/baselines/reference/tsc/noEmit/syntax-errors.js +++ b/testdata/baselines/reference/tsc/noEmit/syntax-errors.js @@ -12,7 +12,7 @@ const a = "hello } tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:17 - error TS1002: Unterminated string literal. @@ -51,7 +51,7 @@ declare const console: { log(msg: any): void; }; Edit [0]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:17 - error TS1002: Unterminated string literal. @@ -107,7 +107,7 @@ Edit [5]:: Introduce error const a = "hello tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:17 - error TS1002: Unterminated string literal. @@ -143,7 +143,7 @@ const a = "hello; Edit [7]:: no change tsgo --noEmit -ExitStatus:: DiagnosticsPresent_OutputsSkipped +ExitStatus:: DiagnosticsPresent_OutputsGenerated Output:: a.ts:1:17 - error TS1002: Unterminated string literal.