Skip to content

Commit

Permalink
Store change file set instead of hasPendingChange to be able to reuse…
Browse files Browse the repository at this point in the history
… the information
  • Loading branch information
sheetalkamat committed Apr 19, 2022
1 parent 1a8abac commit 59f2b5c
Show file tree
Hide file tree
Showing 13 changed files with 533 additions and 140 deletions.
23 changes: 16 additions & 7 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace ts {
/**
* The map has key by source file's path that has been changed
*/
changedFilesSet?: ReadonlySet<Path>;
changedFilesSet: ReadonlySet<Path>;
/**
* Set of affected files being iterated
*/
Expand Down Expand Up @@ -196,11 +196,11 @@ namespace ts {
}
const changedFilesSet = oldState!.changedFilesSet;
if (canCopySemanticDiagnostics) {
Debug.assert(!changedFilesSet || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
Debug.assert(!changedFilesSet.size || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
}

// Copy old state's changed files set
changedFilesSet?.forEach(value => state.changedFilesSet.add(value));
changedFilesSet.forEach(value => state.changedFilesSet.add(value));
if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) {
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
state.affectedFilesPendingEmitKind = oldState!.affectedFilesPendingEmitKind && new Map(oldState!.affectedFilesPendingEmitKind);
Expand Down Expand Up @@ -269,7 +269,7 @@ namespace ts {
});
}

state.buildInfoEmitPending = !!state.changedFilesSet.size;
state.buildInfoEmitPending = !useOldState || state.changedFilesSet.size !== oldState!.changedFilesSet.size;
return state;
}

Expand Down Expand Up @@ -704,12 +704,13 @@ namespace ts {
}
else {
state.seenAffectedFiles!.add((affected as SourceFile).resolvedPath);
// Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted
state.buildInfoEmitPending = true;
if (emitKind !== undefined) {
(state.seenEmittedFiles || (state.seenEmittedFiles = new Map())).set((affected as SourceFile).resolvedPath, emitKind);
}
if (isPendingEmit) {
state.affectedFilesPendingEmitIndex!++;
state.buildInfoEmitPending = true;
}
else {
state.affectedFilesIndex!++;
Expand Down Expand Up @@ -800,7 +801,7 @@ namespace ts {
exportedModulesMap?: ProgramBuildInfoReferencedMap;
semanticDiagnosticsPerFile?: ProgramBuildInfoDiagnostic[];
affectedFilesPendingEmit?: ProgramBuilderInfoFilePendingEmit[];
hasPendingChange?: boolean;
changeFileSet?: readonly ProgramBuildInfoFileId[];
}

/**
Expand Down Expand Up @@ -890,6 +891,13 @@ namespace ts {
}
}

let changeFileSet: ProgramBuildInfoFileId[] | undefined;
if (state.changedFilesSet.size) {
for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) {
(changeFileSet ||= []).push(toFileId(path));
}
}

return {
fileNames,
fileInfos,
Expand All @@ -899,7 +907,7 @@ namespace ts {
exportedModulesMap,
semanticDiagnosticsPerFile,
affectedFilesPendingEmit,
hasPendingChange: state.changedFilesSet?.size ? true : undefined,
changeFileSet,
};

function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
Expand Down Expand Up @@ -1380,6 +1388,7 @@ namespace ts {
affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toFilePath(value[0])),
affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(value[0]), value => value[1]),
affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0,
changedFilesSet: new Set(map(program.changeFileSet, toFilePath)),
};
return {
getState: () => state,
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/tsbuildPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ namespace ts {
buildResult: BuildResultFlags,
errorType: string,
) {
const canEmitBuildInfo = !(buildResult & BuildResultFlags.SyntaxErrors) && program && !outFile(program.getCompilerOptions());
const canEmitBuildInfo = program && !outFile(program.getCompilerOptions());

reportAndStoreErrors(state, resolvedPath, diagnostics);
state.projectStatus.set(resolvedPath, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
Expand Down Expand Up @@ -1529,7 +1529,7 @@ namespace ts {
}

if (buildInfo.program) {
if (buildInfo.program.hasPendingChange ||
if (buildInfo.program.changeFileSet?.length ||
(!buildInfo.program.options?.noEmit && buildInfo.program.affectedFilesPendingEmit?.length)) {
return {
type: UpToDateStatusType.OutOfDateBuildInfo,
Expand Down
15 changes: 12 additions & 3 deletions src/testRunner/unittests/tsbuild/configFileErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ namespace ts {
});

describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in config file", () => {
function descripencyExplaination() {
return [
"During incremental build, tsbuildinfo is not emitted, so declaration option is not present",
"Clean build has declaration option in tsbuildinfo",
];
}

verifyTscWithEdits({
scenario: "configFileErrors",
subScenario: "reports syntax errors in config file",
Expand All @@ -31,13 +38,15 @@ namespace ts {
{
modifyFs: fs => replaceText(fs, "/src/tsconfig.json", ",", `,
"declaration": true,`),
subScenario: "reports syntax errors after change to config file"
subScenario: "reports syntax errors after change to config file",
descripencyExplaination
},
{
modifyFs: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"),
subScenario: "reports syntax errors after change to ts file"
subScenario: "reports syntax errors after change to ts file",
descripencyExplaination,
},
noChangeRun,
{ ...noChangeRun, descripencyExplaination },
{
modifyFs: fs => fs.writeFileSync(
"/src/tsconfig.json",
Expand Down
4 changes: 2 additions & 2 deletions src/testRunner/unittests/tsbuild/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ interface Symbol {
exportedModulesMap?: MapLike<string[]>;
semanticDiagnosticsPerFile?: readonly ReadableProgramBuildInfoDiagnostic[];
affectedFilesPendingEmit?: readonly ReadableProgramBuilderInfoFilePendingEmit[];
hasPendingChange?: boolean
changeFileSet?: readonly string[];
}
type ReadableBuildInfo = Omit<BuildInfo, "program"> & { program: ReadableProgramBuildInfo | undefined; size: number; };
function generateBuildInfoProgramBaseline(sys: System, buildInfoPath: string, buildInfo: BuildInfo) {
Expand All @@ -232,7 +232,7 @@ interface Symbol {
emitKind === BuilderFileEmit.Full ? "Full" :
Debug.assertNever(emitKind)
]),
hasPendingChange: buildInfo.program.hasPendingChange,
changeFileSet: buildInfo.program.changeFileSet?.map(toFileName),
};
const version = buildInfo.version === ts.version ? fakes.version : buildInfo.version;
const result: ReadableBuildInfo = {
Expand Down
3 changes: 1 addition & 2 deletions src/testRunner/unittests/tsbuild/noEmitOnError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ const a = {
const a = {
lastName: 'sdsd'
};`, "utf-8"),
descripencyExplaination: noChangeWithExportsDescripencyRun.descripencyExplaination,
},
noChangeWithExportsDescripencyRun,
noChangeRun,
],
baselinePrograms: true,
});
Expand Down
2 changes: 1 addition & 1 deletion src/testRunner/unittests/tscWatch/incremental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ namespace ts.tscWatch {
});

const state = builderProgram.getState();
assert.equal(state.changedFilesSet!.size, 0, "changes");
assert.equal(state.changedFilesSet.size, 0, "changes");

assert.equal(state.fileInfos.size, 3, "FileInfo size");
assert.deepEqual(state.fileInfos.get(libFile.path as Path), {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
0:: reports syntax errors after change to config file
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
Clean build has declaration option in tsbuildinfo
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
CleanBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4646078106-export function foo() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true,
"declaration": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
IncrementalBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4646078106-export function foo() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
1:: reports syntax errors after change to ts file
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
Clean build has declaration option in tsbuildinfo
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
CleanBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "9819159940-export function foo() { }export function fooBar() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true,
"declaration": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
IncrementalBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4646078106-export function foo() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
2:: no-change-run
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
Clean build has declaration option in tsbuildinfo
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
CleanBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "9819159940-export function foo() { }export function fooBar() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true,
"declaration": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
IncrementalBuild:
{
"program": {
"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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4646078106-export function foo() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true
},
"referencedMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion"
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,44 @@ directoryExists:: {
}


//// [/src/tsconfig.tsbuildinfo]
{"program":{"fileNames":["../lib/lib.d.ts","./a.ts","./b.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; };","signature":false,"affectsGlobalScope":true},{"version":"4646078106-export function foo() { }","signature":false},{"version":"1045484683-export function bar() { }","signature":false}],"options":{"composite":true},"referencedMap":[],"exportedModulesMap":[],"changeFileSet":[1,2,3]},"version":"FakeTSVersion"}

//// [/src/tsconfig.tsbuildinfo.readable.baseline.txt]
{
"program": {
"fileNames": [
"../lib/lib.d.ts",
"./a.ts",
"./b.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; };",
"affectsGlobalScope": true
},
"./a.ts": {
"version": "4646078106-export function foo() { }"
},
"./b.ts": {
"version": "1045484683-export function bar() { }"
}
},
"options": {
"composite": true
},
"referencedMap": {},
"exportedModulesMap": {},
"changeFileSet": [
"../lib/lib.d.ts",
"./a.ts",
"./b.ts"
]
},
"version": "FakeTSVersion",
"size": 834
}



Change:: reports syntax errors after change to config file
Expand Down
Loading

0 comments on commit 59f2b5c

Please sign in to comment.