Skip to content

Commit c671fe1

Browse files
authored
Skip up-to-date checks during force build (#43666)
* Skip up-to-date checks during force build Save work by not checking timestamps or parsing the buildinfo file. Retain correctness checks (like input file existence). Suppress project status, which was confusing anyway. * Print a message to indicate that --force is causing the rebuild * Don't bother updating buildInfoChecked * Add missing force check
1 parent e0d5516 commit c671fe1

File tree

3 files changed

+56
-38
lines changed

3 files changed

+56
-38
lines changed

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -5041,6 +5041,10 @@
50415041
"code": 6387,
50425042
"reportsDeprecated": true
50435043
},
5044+
"Project '{0}' is being forcibly rebuilt": {
5045+
"category": "Message",
5046+
"code": 6388
5047+
},
50445048

50455049
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
50465050
"category": "Message",

src/compiler/tsbuildPublic.ts

+49-35
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,7 @@ namespace ts {
13501350
}
13511351

13521352
function getUpToDateStatusWorker(state: SolutionBuilderState, project: ParsedCommandLine, resolvedPath: ResolvedConfigFilePath): UpToDateStatus {
1353+
const force = !!state.options.force;
13531354
let newestInputFileName: string = undefined!;
13541355
let newestInputFileTime = minimumDate;
13551356
const { host } = state;
@@ -1362,10 +1363,12 @@ namespace ts {
13621363
};
13631364
}
13641365

1365-
const inputTime = getModifiedTime(host, inputFile); host.getModifiedTime(inputFile);
1366-
if (inputTime > newestInputFileTime) {
1367-
newestInputFileName = inputFile;
1368-
newestInputFileTime = inputTime;
1366+
if (!force) {
1367+
const inputTime = getModifiedTime(host, inputFile); host.getModifiedTime(inputFile);
1368+
if (inputTime > newestInputFileTime) {
1369+
newestInputFileName = inputFile;
1370+
newestInputFileTime = inputTime;
1371+
}
13691372
}
13701373
}
13711374

@@ -1387,39 +1390,41 @@ namespace ts {
13871390
let missingOutputFileName: string | undefined;
13881391
let newestDeclarationFileContentChangedTime = minimumDate;
13891392
let isOutOfDateWithInputs = false;
1390-
for (const output of outputs) {
1391-
// Output is missing; can stop checking
1392-
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1393-
if (!host.fileExists(output)) {
1394-
missingOutputFileName = output;
1395-
break;
1396-
}
1393+
if (!force) {
1394+
for (const output of outputs) {
1395+
// Output is missing; can stop checking
1396+
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1397+
if (!host.fileExists(output)) {
1398+
missingOutputFileName = output;
1399+
break;
1400+
}
13971401

1398-
const outputTime = getModifiedTime(host, output);
1399-
if (outputTime < oldestOutputFileTime) {
1400-
oldestOutputFileTime = outputTime;
1401-
oldestOutputFileName = output;
1402-
}
1402+
const outputTime = getModifiedTime(host, output);
1403+
if (outputTime < oldestOutputFileTime) {
1404+
oldestOutputFileTime = outputTime;
1405+
oldestOutputFileName = output;
1406+
}
14031407

1404-
// If an output is older than the newest input, we can stop checking
1405-
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1406-
if (outputTime < newestInputFileTime) {
1407-
isOutOfDateWithInputs = true;
1408-
break;
1409-
}
1408+
// If an output is older than the newest input, we can stop checking
1409+
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1410+
if (outputTime < newestInputFileTime) {
1411+
isOutOfDateWithInputs = true;
1412+
break;
1413+
}
14101414

1411-
if (outputTime > newestOutputFileTime) {
1412-
newestOutputFileTime = outputTime;
1413-
newestOutputFileName = output;
1414-
}
1415+
if (outputTime > newestOutputFileTime) {
1416+
newestOutputFileTime = outputTime;
1417+
newestOutputFileName = output;
1418+
}
14151419

1416-
// Keep track of when the most recent time a .d.ts file was changed.
1417-
// In addition to file timestamps, we also keep track of when a .d.ts file
1418-
// had its file touched but not had its contents changed - this allows us
1419-
// to skip a downstream typecheck
1420-
if (isDeclarationFile(output)) {
1421-
const outputModifiedTime = getModifiedTime(host, output);
1422-
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
1420+
// Keep track of when the most recent time a .d.ts file was changed.
1421+
// In addition to file timestamps, we also keep track of when a .d.ts file
1422+
// had its file touched but not had its contents changed - this allows us
1423+
// to skip a downstream typecheck
1424+
if (isDeclarationFile(output)) {
1425+
const outputModifiedTime = getModifiedTime(host, output);
1426+
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
1427+
}
14231428
}
14241429
}
14251430

@@ -1459,7 +1464,8 @@ namespace ts {
14591464
}
14601465

14611466
// Check oldest output file name only if there is no missing output file name
1462-
if (!missingOutputFileName) {
1467+
// (a check we will have skipped if this is a forced build)
1468+
if (!force && !missingOutputFileName) {
14631469
// If the upstream project's newest file is older than our oldest output, we
14641470
// can't be out of date because of it
14651471
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
@@ -1509,7 +1515,7 @@ namespace ts {
15091515
if (extendedConfigStatus) return extendedConfigStatus;
15101516
}
15111517

1512-
if (!state.buildInfoChecked.has(resolvedPath)) {
1518+
if (!force && !state.buildInfoChecked.has(resolvedPath)) {
15131519
state.buildInfoChecked.set(resolvedPath, true);
15141520
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(project.options);
15151521
if (buildInfoPath) {
@@ -2005,6 +2011,14 @@ namespace ts {
20052011
}
20062012

20072013
function reportUpToDateStatus(state: SolutionBuilderState, configFileName: string, status: UpToDateStatus) {
2014+
if (state.options.force && (status.type === UpToDateStatusType.UpToDate || status.type === UpToDateStatusType.UpToDateWithUpstreamTypes)) {
2015+
return reportStatus(
2016+
state,
2017+
Diagnostics.Project_0_is_being_forcibly_rebuilt,
2018+
relName(state, configFileName)
2019+
);
2020+
}
2021+
20082022
switch (status.type) {
20092023
case UpToDateStatusType.OutOfDateWithSelf:
20102024
return reportStatus(

tests/baselines/reference/tsbuild/sample1/incremental-declaration-changes/rebuilds-from-start-if-force-option-is-set.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ Output::
88
* src/logic/tsconfig.json
99
* src/tests/tsconfig.json
1010

11-
[[90m12:16:00 AM[0m] Project 'src/core/tsconfig.json' is up to date because newest input 'src/core/anotherModule.ts' is older than oldest output 'src/core/anotherModule.js'
11+
[[90m12:16:00 AM[0m] Project 'src/core/tsconfig.json' is being forcibly rebuilt
1212

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

15-
[[90m12:16:00 AM[0m] Project 'src/logic/tsconfig.json' is up to date with .d.ts files from its dependencies
15+
[[90m12:16:00 AM[0m] Project 'src/logic/tsconfig.json' is being forcibly rebuilt
1616

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

19-
[[90m12:16:00 AM[0m] Project 'src/tests/tsconfig.json' is up to date with .d.ts files from its dependencies
19+
[[90m12:16:00 AM[0m] Project 'src/tests/tsconfig.json' is being forcibly rebuilt
2020

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

0 commit comments

Comments
 (0)