Skip to content
Permalink
Browse files
During uptodate ness check with buildInfo, check if there are errors …
…explicitly with noEmit (#50974)

* Add test

* During uptodate ness check, with buildInfo, check if there are errors in the program to determine uptodateness
Fixes #50959

* Comment update
  • Loading branch information
sheetalkamat committed Sep 27, 2022
1 parent 63791f5 commit 16faef1d8d522b66b6c672bdd15b4026e2018a62
Show file tree
Hide file tree
Showing 7 changed files with 811 additions and 1 deletion.
@@ -1609,8 +1609,16 @@ namespace ts {

if (buildInfo.program) {
// If there are pending changes that are not emitted, project is out of date
// When there are syntax errors, changeFileSet will have list of files changed (irrespective of noEmit)
// But in case of semantic error we need special treatment.
// Checking presence of affectedFilesPendingEmit list is fast and good way to tell if there were semantic errors and file emit was blocked
// But if noEmit is true, affectedFilesPendingEmit will have file list even if there are no semantic errors to preserve list of files to be emitted when running with noEmit false
// So with noEmit set to true, check on semantic diagnostics needs to be explicit as oppose to when it is false when only files pending emit is sufficient
if ((buildInfo.program as ProgramMultiFileEmitBuildInfo).changeFileSet?.length ||
(!project.options.noEmit && (buildInfo.program as ProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length)) {
(!project.options.noEmit ?
(buildInfo.program as ProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length :
some((buildInfo.program as ProgramMultiFileEmitBuildInfo).semanticDiagnosticsPerFile, isArray))
) {
return {
type: UpToDateStatusType.OutOfDateBuildInfo,
buildInfoFile: buildInfoPath
@@ -132,6 +132,7 @@
"unittests/tsbuild/lateBoundSymbol.ts",
"unittests/tsbuild/moduleResolution.ts",
"unittests/tsbuild/moduleSpecifiers.ts",
"unittests/tsbuild/noEmit.ts",
"unittests/tsbuild/noEmitOnError.ts",
"unittests/tsbuild/outFile.ts",
"unittests/tsbuild/outputPaths.ts",
@@ -0,0 +1,34 @@
namespace ts {
describe("unittests:: tsbuild:: noEmit", () => {
function verifyNoEmitWorker(subScenario: string, aTsContent: string, commandLineArgs: readonly string[]) {
verifyTscWithEdits({
scenario: "noEmit",
subScenario,
fs: () => loadProjectFromFiles({
"/src/a.ts": aTsContent,
"/src/tsconfig.json": JSON.stringify({
compilerOptions: { noEmit: true }
})
}),
commandLineArgs,
edits: [
noChangeRun,
{
subScenario: "Fix error",
modifyFs: fs => fs.writeFileSync("/src/a.ts", `const a = "hello"`),
},
noChangeRun,
],
baselinePrograms: true,
});
}

function verifyNoEmit(subScenario: string, aTsContent: string) {
verifyNoEmitWorker(subScenario, aTsContent, ["--b", "/src/tsconfig.json", "-v"]);
verifyNoEmitWorker(`${subScenario} with incremental`, aTsContent, ["--b", "/src/tsconfig.json", "-v", "--incremental"]);
}

verifyNoEmit("syntax errors", `const a = "hello`);
verifyNoEmit("semantic errors", `const a: number = "hello"`);
});
}
@@ -0,0 +1,234 @@
Input::
//// [/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };

//// [/src/a.ts]
const a: number = "hello"

//// [/src/tsconfig.json]
{"compilerOptions":{"noEmit":true}}



Output::
/lib/tsc --b /src/tsconfig.json -v --incremental
[12:00:08 AM] Projects in this build:
* src/tsconfig.json

[12:00:09 AM] Project 'src/tsconfig.json' is out of date because output file 'src/tsconfig.tsbuildinfo' does not exist

[12:00:10 AM] Building project '/src/tsconfig.json'...

src/a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'.

1 const a: number = "hello"
   ~


Found 1 error.

exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
Program root files: ["/src/a.ts"]
Program options: {"noEmit":true,"incremental":true,"configFilePath":"/src/tsconfig.json"}
Program structureReused: Not
Program files::
/lib/lib.d.ts
/src/a.ts

Semantic diagnostics in builder refreshed for::
/lib/lib.d.ts
/src/a.ts

Shape signatures in builder refreshed for::
/lib/lib.d.ts (used version)
/src/a.ts (used version)


//// [/src/tsconfig.tsbuildinfo]
{"program":{"fileNames":["../lib/lib.d.ts","./a.ts"],"fileInfos":[{"version":"3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"1311033573-const a: number = \"hello\"","affectsGlobalScope":true}],"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[2,[{"file":"./a.ts","start":6,"length":1,"code":2322,"category":1,"messageText":"Type 'string' is not assignable to type 'number'."}]]],"affectedFilesPendingEmit":[[2,1]]},"version":"FakeTSVersion"}

//// [/src/tsconfig.tsbuildinfo.readable.baseline.txt]
{
"program": {
"fileNames": [
"../lib/lib.d.ts",
"./a.ts"
],
"fileInfos": {
"../lib/lib.d.ts": {
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "1311033573-const a: number = \"hello\"",
"signature": "1311033573-const a: number = \"hello\"",
"affectsGlobalScope": true
}
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"../lib/lib.d.ts",
[
"./a.ts",
[
{
"file": "./a.ts",
"start": 6,
"length": 1,
"code": 2322,
"category": 1,
"messageText": "Type 'string' is not assignable to type 'number'."
}
]
]
],
"affectedFilesPendingEmit": [
[
"./a.ts",
"Full"
]
]
},
"version": "FakeTSVersion",
"size": 899
}



Change:: no-change-run
Input::


Output::
/lib/tsc --b /src/tsconfig.json -v --incremental
[12:00:14 AM] Projects in this build:
* src/tsconfig.json

[12:00:15 AM] Project 'src/tsconfig.json' is out of date because buildinfo file 'src/tsconfig.tsbuildinfo' indicates that some of the changes were not emitted

[12:00:16 AM] Building project '/src/tsconfig.json'...

src/a.ts:1:7 - error TS2322: Type 'string' is not assignable to type 'number'.

1 const a: number = "hello"
   ~


Found 1 error.

exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped
Program root files: ["/src/a.ts"]
Program options: {"noEmit":true,"incremental":true,"configFilePath":"/src/tsconfig.json"}
Program structureReused: Not
Program files::
/lib/lib.d.ts
/src/a.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::




Change:: Fix error
Input::
//// [/src/a.ts]
const a = "hello"



Output::
/lib/tsc --b /src/tsconfig.json -v --incremental
[12:00:18 AM] Projects in this build:
* src/tsconfig.json

[12:00:19 AM] Project 'src/tsconfig.json' is out of date because buildinfo file 'src/tsconfig.tsbuildinfo' indicates that some of the changes were not emitted

[12:00:20 AM] Building project '/src/tsconfig.json'...

exitCode:: ExitStatus.Success
Program root files: ["/src/a.ts"]
Program options: {"noEmit":true,"incremental":true,"configFilePath":"/src/tsconfig.json"}
Program structureReused: Not
Program files::
/lib/lib.d.ts
/src/a.ts

Semantic diagnostics in builder refreshed for::
/lib/lib.d.ts
/src/a.ts

Shape signatures in builder refreshed for::
/src/a.ts (computed .d.ts)


//// [/src/tsconfig.tsbuildinfo]
{"program":{"fileNames":["../lib/lib.d.ts","./a.ts"],"fileInfos":[{"version":"3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"4011451714-const a = \"hello\"","signature":"-4100694204-declare const a = \"hello\";\r\n","affectsGlobalScope":true}],"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,2],"affectedFilesPendingEmit":[[2,1]]},"version":"FakeTSVersion"}

//// [/src/tsconfig.tsbuildinfo.readable.baseline.txt]
{
"program": {
"fileNames": [
"../lib/lib.d.ts",
"./a.ts"
],
"fileInfos": {
"../lib/lib.d.ts": {
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4011451714-const a = \"hello\"",
"signature": "-4100694204-declare const a = \"hello\";\r\n",
"affectsGlobalScope": true
}
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"../lib/lib.d.ts",
"./a.ts"
],
"affectedFilesPendingEmit": [
[
"./a.ts",
"Full"
]
]
},
"version": "FakeTSVersion",
"size": 816
}



Change:: no-change-run
Input::


Output::
/lib/tsc --b /src/tsconfig.json -v --incremental
[12:00:24 AM] Projects in this build:
* src/tsconfig.json

[12:00:25 AM] Project 'src/tsconfig.json' is up to date because newest input 'src/a.ts' is older than output 'src/tsconfig.tsbuildinfo'

exitCode:: ExitStatus.Success


0 comments on commit 16faef1

Please sign in to comment.