Skip to content

Commit 59f2b5c

Browse files
committed
Store change file set instead of hasPendingChange to be able to reuse the information
1 parent 1a8abac commit 59f2b5c

13 files changed

+533
-140
lines changed

Diff for: src/compiler/builder.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace ts {
2828
/**
2929
* The map has key by source file's path that has been changed
3030
*/
31-
changedFilesSet?: ReadonlySet<Path>;
31+
changedFilesSet: ReadonlySet<Path>;
3232
/**
3333
* Set of affected files being iterated
3434
*/
@@ -196,11 +196,11 @@ namespace ts {
196196
}
197197
const changedFilesSet = oldState!.changedFilesSet;
198198
if (canCopySemanticDiagnostics) {
199-
Debug.assert(!changedFilesSet || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
199+
Debug.assert(!changedFilesSet.size || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
200200
}
201201

202202
// Copy old state's changed files set
203-
changedFilesSet?.forEach(value => state.changedFilesSet.add(value));
203+
changedFilesSet.forEach(value => state.changedFilesSet.add(value));
204204
if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) {
205205
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
206206
state.affectedFilesPendingEmitKind = oldState!.affectedFilesPendingEmitKind && new Map(oldState!.affectedFilesPendingEmitKind);
@@ -269,7 +269,7 @@ namespace ts {
269269
});
270270
}
271271

272-
state.buildInfoEmitPending = !!state.changedFilesSet.size;
272+
state.buildInfoEmitPending = !useOldState || state.changedFilesSet.size !== oldState!.changedFilesSet.size;
273273
return state;
274274
}
275275

@@ -704,12 +704,13 @@ namespace ts {
704704
}
705705
else {
706706
state.seenAffectedFiles!.add((affected as SourceFile).resolvedPath);
707+
// Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted
708+
state.buildInfoEmitPending = true;
707709
if (emitKind !== undefined) {
708710
(state.seenEmittedFiles || (state.seenEmittedFiles = new Map())).set((affected as SourceFile).resolvedPath, emitKind);
709711
}
710712
if (isPendingEmit) {
711713
state.affectedFilesPendingEmitIndex!++;
712-
state.buildInfoEmitPending = true;
713714
}
714715
else {
715716
state.affectedFilesIndex!++;
@@ -800,7 +801,7 @@ namespace ts {
800801
exportedModulesMap?: ProgramBuildInfoReferencedMap;
801802
semanticDiagnosticsPerFile?: ProgramBuildInfoDiagnostic[];
802803
affectedFilesPendingEmit?: ProgramBuilderInfoFilePendingEmit[];
803-
hasPendingChange?: boolean;
804+
changeFileSet?: readonly ProgramBuildInfoFileId[];
804805
}
805806

806807
/**
@@ -890,6 +891,13 @@ namespace ts {
890891
}
891892
}
892893

894+
let changeFileSet: ProgramBuildInfoFileId[] | undefined;
895+
if (state.changedFilesSet.size) {
896+
for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) {
897+
(changeFileSet ||= []).push(toFileId(path));
898+
}
899+
}
900+
893901
return {
894902
fileNames,
895903
fileInfos,
@@ -899,7 +907,7 @@ namespace ts {
899907
exportedModulesMap,
900908
semanticDiagnosticsPerFile,
901909
affectedFilesPendingEmit,
902-
hasPendingChange: state.changedFilesSet?.size ? true : undefined,
910+
changeFileSet,
903911
};
904912

905913
function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
@@ -1380,6 +1388,7 @@ namespace ts {
13801388
affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toFilePath(value[0])),
13811389
affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(value[0]), value => value[1]),
13821390
affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0,
1391+
changedFilesSet: new Set(map(program.changeFileSet, toFilePath)),
13831392
};
13841393
return {
13851394
getState: () => state,

Diff for: src/compiler/tsbuildPublic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ namespace ts {
13361336
buildResult: BuildResultFlags,
13371337
errorType: string,
13381338
) {
1339-
const canEmitBuildInfo = !(buildResult & BuildResultFlags.SyntaxErrors) && program && !outFile(program.getCompilerOptions());
1339+
const canEmitBuildInfo = program && !outFile(program.getCompilerOptions());
13401340

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

15311531
if (buildInfo.program) {
1532-
if (buildInfo.program.hasPendingChange ||
1532+
if (buildInfo.program.changeFileSet?.length ||
15331533
(!buildInfo.program.options?.noEmit && buildInfo.program.affectedFilesPendingEmit?.length)) {
15341534
return {
15351535
type: UpToDateStatusType.OutOfDateBuildInfo,

Diff for: src/testRunner/unittests/tsbuild/configFileErrors.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ namespace ts {
99
});
1010

1111
describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in config file", () => {
12+
function descripencyExplaination() {
13+
return [
14+
"During incremental build, tsbuildinfo is not emitted, so declaration option is not present",
15+
"Clean build has declaration option in tsbuildinfo",
16+
];
17+
}
18+
1219
verifyTscWithEdits({
1320
scenario: "configFileErrors",
1421
subScenario: "reports syntax errors in config file",
@@ -31,13 +38,15 @@ namespace ts {
3138
{
3239
modifyFs: fs => replaceText(fs, "/src/tsconfig.json", ",", `,
3340
"declaration": true,`),
34-
subScenario: "reports syntax errors after change to config file"
41+
subScenario: "reports syntax errors after change to config file",
42+
descripencyExplaination
3543
},
3644
{
3745
modifyFs: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"),
38-
subScenario: "reports syntax errors after change to ts file"
46+
subScenario: "reports syntax errors after change to ts file",
47+
descripencyExplaination,
3948
},
40-
noChangeRun,
49+
{ ...noChangeRun, descripencyExplaination },
4150
{
4251
modifyFs: fs => fs.writeFileSync(
4352
"/src/tsconfig.json",

Diff for: src/testRunner/unittests/tsbuild/helpers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ interface Symbol {
207207
exportedModulesMap?: MapLike<string[]>;
208208
semanticDiagnosticsPerFile?: readonly ReadableProgramBuildInfoDiagnostic[];
209209
affectedFilesPendingEmit?: readonly ReadableProgramBuilderInfoFilePendingEmit[];
210-
hasPendingChange?: boolean
210+
changeFileSet?: readonly string[];
211211
}
212212
type ReadableBuildInfo = Omit<BuildInfo, "program"> & { program: ReadableProgramBuildInfo | undefined; size: number; };
213213
function generateBuildInfoProgramBaseline(sys: System, buildInfoPath: string, buildInfo: BuildInfo) {
@@ -232,7 +232,7 @@ interface Symbol {
232232
emitKind === BuilderFileEmit.Full ? "Full" :
233233
Debug.assertNever(emitKind)
234234
]),
235-
hasPendingChange: buildInfo.program.hasPendingChange,
235+
changeFileSet: buildInfo.program.changeFileSet?.map(toFileName),
236236
};
237237
const version = buildInfo.version === ts.version ? fakes.version : buildInfo.version;
238238
const result: ReadableBuildInfo = {

Diff for: src/testRunner/unittests/tsbuild/noEmitOnError.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ const a = {
4040
const a = {
4141
lastName: 'sdsd'
4242
};`, "utf-8"),
43-
descripencyExplaination: noChangeWithExportsDescripencyRun.descripencyExplaination,
4443
},
45-
noChangeWithExportsDescripencyRun,
44+
noChangeRun,
4645
],
4746
baselinePrograms: true,
4847
});

Diff for: src/testRunner/unittests/tscWatch/incremental.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ namespace ts.tscWatch {
155155
});
156156

157157
const state = builderProgram.getState();
158-
assert.equal(state.changedFilesSet!.size, 0, "changes");
158+
assert.equal(state.changedFilesSet.size, 0, "changes");
159159

160160
assert.equal(state.fileInfos.size, 3, "FileInfo size");
161161
assert.deepEqual(state.fileInfos.get(libFile.path as Path), {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
0:: reports syntax errors after change to config file
2+
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
3+
Clean build has declaration option in tsbuildinfo
4+
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
5+
CleanBuild:
6+
{
7+
"program": {
8+
"fileInfos": {
9+
"../lib/lib.d.ts": {
10+
"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; };",
11+
"affectsGlobalScope": true
12+
},
13+
"./a.ts": {
14+
"version": "4646078106-export function foo() { }"
15+
},
16+
"./b.ts": {
17+
"version": "1045484683-export function bar() { }"
18+
}
19+
},
20+
"options": {
21+
"composite": true,
22+
"declaration": true
23+
},
24+
"referencedMap": {},
25+
"changeFileSet": [
26+
"../lib/lib.d.ts",
27+
"./a.ts",
28+
"./b.ts"
29+
]
30+
},
31+
"version": "FakeTSVersion"
32+
}
33+
IncrementalBuild:
34+
{
35+
"program": {
36+
"fileInfos": {
37+
"../lib/lib.d.ts": {
38+
"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; };",
39+
"affectsGlobalScope": true
40+
},
41+
"./a.ts": {
42+
"version": "4646078106-export function foo() { }"
43+
},
44+
"./b.ts": {
45+
"version": "1045484683-export function bar() { }"
46+
}
47+
},
48+
"options": {
49+
"composite": true
50+
},
51+
"referencedMap": {},
52+
"changeFileSet": [
53+
"../lib/lib.d.ts",
54+
"./a.ts",
55+
"./b.ts"
56+
]
57+
},
58+
"version": "FakeTSVersion"
59+
}
60+
1:: reports syntax errors after change to ts file
61+
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
62+
Clean build has declaration option in tsbuildinfo
63+
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
64+
CleanBuild:
65+
{
66+
"program": {
67+
"fileInfos": {
68+
"../lib/lib.d.ts": {
69+
"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; };",
70+
"affectsGlobalScope": true
71+
},
72+
"./a.ts": {
73+
"version": "9819159940-export function foo() { }export function fooBar() { }"
74+
},
75+
"./b.ts": {
76+
"version": "1045484683-export function bar() { }"
77+
}
78+
},
79+
"options": {
80+
"composite": true,
81+
"declaration": true
82+
},
83+
"referencedMap": {},
84+
"changeFileSet": [
85+
"../lib/lib.d.ts",
86+
"./a.ts",
87+
"./b.ts"
88+
]
89+
},
90+
"version": "FakeTSVersion"
91+
}
92+
IncrementalBuild:
93+
{
94+
"program": {
95+
"fileInfos": {
96+
"../lib/lib.d.ts": {
97+
"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; };",
98+
"affectsGlobalScope": true
99+
},
100+
"./a.ts": {
101+
"version": "4646078106-export function foo() { }"
102+
},
103+
"./b.ts": {
104+
"version": "1045484683-export function bar() { }"
105+
}
106+
},
107+
"options": {
108+
"composite": true
109+
},
110+
"referencedMap": {},
111+
"changeFileSet": [
112+
"../lib/lib.d.ts",
113+
"./a.ts",
114+
"./b.ts"
115+
]
116+
},
117+
"version": "FakeTSVersion"
118+
}
119+
2:: no-change-run
120+
During incremental build, tsbuildinfo is not emitted, so declaration option is not present
121+
Clean build has declaration option in tsbuildinfo
122+
TsBuild info text without affectedFilesPendingEmit:: /src/tsconfig.tsbuildinfo.readable.baseline.txt::
123+
CleanBuild:
124+
{
125+
"program": {
126+
"fileInfos": {
127+
"../lib/lib.d.ts": {
128+
"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; };",
129+
"affectsGlobalScope": true
130+
},
131+
"./a.ts": {
132+
"version": "9819159940-export function foo() { }export function fooBar() { }"
133+
},
134+
"./b.ts": {
135+
"version": "1045484683-export function bar() { }"
136+
}
137+
},
138+
"options": {
139+
"composite": true,
140+
"declaration": true
141+
},
142+
"referencedMap": {},
143+
"changeFileSet": [
144+
"../lib/lib.d.ts",
145+
"./a.ts",
146+
"./b.ts"
147+
]
148+
},
149+
"version": "FakeTSVersion"
150+
}
151+
IncrementalBuild:
152+
{
153+
"program": {
154+
"fileInfos": {
155+
"../lib/lib.d.ts": {
156+
"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; };",
157+
"affectsGlobalScope": true
158+
},
159+
"./a.ts": {
160+
"version": "4646078106-export function foo() { }"
161+
},
162+
"./b.ts": {
163+
"version": "1045484683-export function bar() { }"
164+
}
165+
},
166+
"options": {
167+
"composite": true
168+
},
169+
"referencedMap": {},
170+
"changeFileSet": [
171+
"../lib/lib.d.ts",
172+
"./a.ts",
173+
"./b.ts"
174+
]
175+
},
176+
"version": "FakeTSVersion"
177+
}

Diff for: tests/baselines/reference/tsbuild/configFileErrors/reports-syntax-errors-in-config-file.js

+38
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,44 @@ directoryExists:: {
6161
}
6262

6363

64+
//// [/src/tsconfig.tsbuildinfo]
65+
{"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"}
66+
67+
//// [/src/tsconfig.tsbuildinfo.readable.baseline.txt]
68+
{
69+
"program": {
70+
"fileNames": [
71+
"../lib/lib.d.ts",
72+
"./a.ts",
73+
"./b.ts"
74+
],
75+
"fileInfos": {
76+
"../lib/lib.d.ts": {
77+
"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; };",
78+
"affectsGlobalScope": true
79+
},
80+
"./a.ts": {
81+
"version": "4646078106-export function foo() { }"
82+
},
83+
"./b.ts": {
84+
"version": "1045484683-export function bar() { }"
85+
}
86+
},
87+
"options": {
88+
"composite": true
89+
},
90+
"referencedMap": {},
91+
"exportedModulesMap": {},
92+
"changeFileSet": [
93+
"../lib/lib.d.ts",
94+
"./a.ts",
95+
"./b.ts"
96+
]
97+
},
98+
"version": "FakeTSVersion",
99+
"size": 834
100+
}
101+
64102

65103

66104
Change:: reports syntax errors after change to config file

0 commit comments

Comments
 (0)