From af36a859b96e056a7e1dba62fdc3825ffc1e9408 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 29 Nov 2022 12:20:09 -0800 Subject: [PATCH] Fix the crash when affected file pending emit is not in program is being serialized into buildInfo (#51674) Fixes #51641 --- src/compiler/builder.ts | 4 +- src/testRunner/unittests/tsc/incremental.ts | 21 ++ ...-before-fixing-error-with-noEmitOnError.js | 213 ++++++++++++++++++ 3 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/tsc/incremental/file-deleted-before-fixing-error-with-noEmitOnError.js diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 6002189104f9b..811ab5f35a95a 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -1078,8 +1078,8 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde const seenFiles = new Set(); for (const path of arrayFrom(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { if (tryAddToSet(seenFiles, path)) { - const file = state.program!.getSourceFileByPath(path)!; - if (!sourceFileMayBeEmitted(file, state.program!)) continue; + const file = state.program!.getSourceFileByPath(path); + if (!file || !sourceFileMayBeEmitted(file, state.program!)) continue; const fileId = toFileId(path), pendingEmit = state.affectedFilesPendingEmit.get(path)!; (affectedFilesPendingEmit ||= []).push( pendingEmit === fullEmitForOptions ? diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index d41f933947218..65952a560cd1c 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -855,4 +855,25 @@ console.log(a);`, }, ] }); + + verifyTscWithEdits({ + scenario: "incremental", + subScenario: "file deleted before fixing error with noEmitOnError", + fs: () => loadProjectFromFiles({ + "/src/project/tsconfig.json": JSON.stringify({ + compilerOptions: { + outDir: "outDir", + noEmitOnError: true, + }, + }), + "/src/project/file1.ts": `export const x: 30 = "hello";`, + "/src/project/file2.ts": `export class D { }`, + }), + commandLineArgs: ["--p", "/src/project", "-i"], + edits: [{ + subScenario: "delete file without error", + modifyFs: fs => fs.unlinkSync("/src/project/file2.ts"), + }], + baselinePrograms: true, + }); }); diff --git a/tests/baselines/reference/tsc/incremental/file-deleted-before-fixing-error-with-noEmitOnError.js b/tests/baselines/reference/tsc/incremental/file-deleted-before-fixing-error-with-noEmitOnError.js new file mode 100644 index 0000000000000..8577fb24ec7bb --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/file-deleted-before-fixing-error-with-noEmitOnError.js @@ -0,0 +1,213 @@ +Input:: +//// [/lib/lib.d.ts] +/// +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 {} +declare const console: { log(msg: any): void; }; + +//// [/src/project/file1.ts] +export const x: 30 = "hello"; + +//// [/src/project/file2.ts] +export class D { } + +//// [/src/project/tsconfig.json] +{"compilerOptions":{"outDir":"outDir","noEmitOnError":true}} + + + +Output:: +/lib/tsc --p /src/project -i +src/project/file1.ts:1:14 - error TS2322: Type '"hello"' is not assignable to type '30'. + +1 export const x: 30 = "hello"; +   ~ + + +Found 1 error in src/project/file1.ts:1 + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped +Program root files: ["/src/project/file1.ts","/src/project/file2.ts"] +Program options: {"outDir":"/src/project/outDir","noEmitOnError":true,"project":"/src/project","incremental":true,"configFilePath":"/src/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/lib/lib.d.ts +/src/project/file1.ts +/src/project/file2.ts + +Semantic diagnostics in builder refreshed for:: +/lib/lib.d.ts +/src/project/file1.ts +/src/project/file2.ts + +Shape signatures in builder refreshed for:: +/lib/lib.d.ts (used version) +/src/project/file1.ts (used version) +/src/project/file2.ts (used version) + + +//// [/src/project/outDir/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../file1.ts","../file2.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},"-10927263693-export const x: 30 = \"hello\";","-7804761415-export class D { }"],"options":{"noEmitOnError":true,"outDir":"./"},"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[2,[{"file":"../file1.ts","start":13,"length":1,"code":2322,"category":1,"messageText":"Type '\"hello\"' is not assignable to type '30'."}]],3],"affectedFilesPendingEmit":[2,3]},"version":"FakeTSVersion"} + +//// [/src/project/outDir/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../file1.ts", + "../file2.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "original": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../file1.ts": { + "version": "-10927263693-export const x: 30 = \"hello\";", + "signature": "-10927263693-export const x: 30 = \"hello\";" + }, + "../file2.ts": { + "version": "-7804761415-export class D { }", + "signature": "-7804761415-export class D { }" + } + }, + "options": { + "noEmitOnError": true, + "outDir": "./" + }, + "referencedMap": {}, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts", + [ + "../file1.ts", + [ + { + "file": "../file1.ts", + "start": 13, + "length": 1, + "code": 2322, + "category": 1, + "messageText": "Type '\"hello\"' is not assignable to type '30'." + } + ] + ], + "../file2.ts" + ], + "affectedFilesPendingEmit": [ + [ + "../file1.ts", + "Js" + ], + [ + "../file2.ts", + "Js" + ] + ] + }, + "version": "FakeTSVersion", + "size": 977 +} + + + +Change:: delete file without error +Input:: +//// [/src/project/file2.ts] unlink + + +Output:: +/lib/tsc --p /src/project -i +src/project/file1.ts:1:14 - error TS2322: Type '"hello"' is not assignable to type '30'. + +1 export const x: 30 = "hello"; +   ~ + + +Found 1 error in src/project/file1.ts:1 + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped +Program root files: ["/src/project/file1.ts"] +Program options: {"outDir":"/src/project/outDir","noEmitOnError":true,"project":"/src/project","incremental":true,"configFilePath":"/src/project/tsconfig.json"} +Program structureReused: Not +Program files:: +/lib/lib.d.ts +/src/project/file1.ts + +Semantic diagnostics in builder refreshed for:: + +No shapes updated in the builder:: + + +//// [/src/project/outDir/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../file1.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},"-10927263693-export const x: 30 = \"hello\";"],"options":{"noEmitOnError":true,"outDir":"./"},"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[2,[{"file":"../file1.ts","start":13,"length":1,"code":2322,"category":1,"messageText":"Type '\"hello\"' is not assignable to type '30'."}]]],"affectedFilesPendingEmit":[2]},"version":"FakeTSVersion"} + +//// [/src/project/outDir/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../file1.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "original": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../file1.ts": { + "version": "-10927263693-export const x: 30 = \"hello\";", + "signature": "-10927263693-export const x: 30 = \"hello\";" + } + }, + "options": { + "noEmitOnError": true, + "outDir": "./" + }, + "referencedMap": {}, + "exportedModulesMap": {}, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts", + [ + "../file1.ts", + [ + { + "file": "../file1.ts", + "start": 13, + "length": 1, + "code": 2322, + "category": 1, + "messageText": "Type '\"hello\"' is not assignable to type '30'." + } + ] + ] + ], + "affectedFilesPendingEmit": [ + [ + "../file1.ts", + "Js" + ] + ] + }, + "version": "FakeTSVersion", + "size": 926 +} +