Skip to content

Commit 49286d6

Browse files
committed
Write buildInfo irrespective of incremental if invoked from tsc --b
1 parent 7ad8f39 commit 49286d6

File tree

167 files changed

+2232
-275
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+2232
-275
lines changed

src/compiler/builder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import {
5656
HostForComputeHash,
5757
isArray,
5858
isDeclarationFileName,
59+
isIncrementalCompilation,
5960
isJsonSourceFile,
6061
isNumber,
6162
isString,
@@ -349,7 +350,7 @@ function createBuilderProgramState(newProgram: Program, oldState: Readonly<Reusa
349350
}
350351
else {
351352
// We arent using old state, so atleast emit buildInfo with current information
352-
state.buildInfoEmitPending = true;
353+
state.buildInfoEmitPending = isIncrementalCompilation(compilerOptions);
353354
}
354355

355356
// Update changed files and copy semantic diagnostics if we can
@@ -1095,6 +1096,9 @@ function getBuildInfo(state: BuilderProgramState): BuildInfo {
10951096
const fileNames: string[] = [];
10961097
const fileNameToFileId = new Map<string, ProgramBuildInfoFileId>();
10971098
const rootFileNames = new Set(state.program!.getRootFileNames().map(f => toPath(f, currentDirectory, state.program!.getCanonicalFileName)));
1099+
1100+
if (!isIncrementalCompilation(state.compilerOptions)) return createBuildInfo(/*program*/ undefined);
1101+
10981102
const root: ProgramBuildInfoRoot[] = [];
10991103
if (state.compilerOptions.outFile) {
11001104
// Copy all fileInfo, version and impliedFormat

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4609,6 +4609,10 @@
46094609
"category": "Error",
46104610
"code": 5110
46114611
},
4612+
"Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or 'composite' or if not running 'tsc -b'.": {
4613+
"category": "Error",
4614+
"code": 5111
4615+
},
46124616

46134617
"Generates a sourcemap for each corresponding '.d.ts' file.": {
46144618
"category": "Message",

src/compiler/emitter.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ export function forEachEmittedFile<T>(
478478

479479
export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) {
480480
const configFile = options.configFilePath;
481-
if (!isIncrementalCompilation(options)) return undefined;
481+
if (!canEmitTsBuildInfo(options)) return undefined;
482482
if (options.tsBuildInfoFile) return options.tsBuildInfoFile;
483483
const outPath = options.outFile;
484484
let buildInfoExtensionLess: string;
@@ -497,6 +497,11 @@ export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) {
497497
return buildInfoExtensionLess + Extension.TsBuildInfo;
498498
}
499499

500+
/** @internal */
501+
export function canEmitTsBuildInfo(options: CompilerOptions) {
502+
return isIncrementalCompilation(options) || (options.tscBuild && !options.noEmit);
503+
}
504+
500505
/** @internal */
501506
export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: boolean): EmitFileNames {
502507
const outPath = options.outFile!;

src/compiler/program.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
AsExpression,
99
BuilderProgram,
1010
CancellationToken,
11+
canEmitTsBuildInfo,
1112
canHaveDecorators,
1213
canHaveIllegalDecorators,
1314
chainDiagnosticMessages,
@@ -195,7 +196,6 @@ import {
195196
isImportEqualsDeclaration,
196197
isImportSpecifier,
197198
isImportTypeNode,
198-
isIncrementalCompilation,
199199
isInJSFile,
200200
isJSDocImportTag,
201201
isLiteralImportTypeNode,
@@ -4299,8 +4299,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
42994299

43004300
const outputFile = options.outFile;
43014301
if (options.tsBuildInfoFile) {
4302-
if (!isIncrementalCompilation(options)) {
4303-
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite");
4302+
if (!canEmitTsBuildInfo(options)) {
4303+
createDiagnosticForOptionName(Diagnostics.Option_tsBuildInfoFile_cannot_be_specified_without_specifying_option_incremental_or_composite_or_if_not_running_tsc_b, "tsBuildInfoFile");
43044304
}
43054305
}
43064306
else if (options.incremental && !outputFile && !options.configFilePath) {

src/compiler/tsbuildPublic.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerO
326326
commonOptionsWithBuild.forEach(option => {
327327
if (hasProperty(buildOptions, option.name)) result[option.name] = buildOptions[option.name];
328328
});
329+
result.tscBuild = true;
329330
return result;
330331
}
331332

@@ -1460,7 +1461,7 @@ function buildErrors<T extends BuilderProgram>(
14601461
errorType: string,
14611462
) {
14621463
// Since buildinfo has changeset and diagnostics when doing multi file emit, only --out cannot emit buildinfo if it has errors
1463-
const canEmitBuildInfo = program && !program.getCompilerOptions().outFile;
1464+
const canEmitBuildInfo = program && !program.getCompilerOptions().outFile && isIncrementalCompilation(program.getCompilerOptions());
14641465

14651466
reportAndStoreErrors(state, resolvedPath, diagnostics);
14661467
state.projectStatus.set(resolvedPath, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
@@ -1652,6 +1653,7 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
16521653
let buildInfoTime: Date | undefined;
16531654
let buildInfoProgram: ProgramBuildInfo | undefined;
16541655
let buildInfoVersionMap: ReturnType<typeof getBuildInfoFileVersionMap> | undefined;
1656+
const isIncremental = isIncrementalCompilation(project.options);
16551657
if (buildInfoPath) {
16561658
const buildInfoCacheEntry = getBuildInfoCacheEntry(state, buildInfoPath, resolvedPath);
16571659
buildInfoTime = buildInfoCacheEntry?.modifiedTime || ts_getModifiedTime(host, buildInfoPath);
@@ -1677,7 +1679,7 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
16771679
fileName: buildInfoPath,
16781680
};
16791681
}
1680-
if (buildInfo.program && buildInfo.version !== version) {
1682+
if ((buildInfo.program || !isIncremental) && buildInfo.version !== version) {
16811683
return {
16821684
type: UpToDateStatusType.TsVersionOutputOfDate,
16831685
version: buildInfo.version,
@@ -1735,7 +1737,7 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
17351737

17361738
const inputPath = buildInfoProgram ? toPath(state, inputFile) : undefined;
17371739
// If an buildInfo is older than the newest input, we can stop checking
1738-
if (buildInfoTime && buildInfoTime < inputTime) {
1740+
if (isIncremental && buildInfoTime && buildInfoTime < inputTime) {
17391741
let version: string | undefined;
17401742
let currentVersion: string | undefined;
17411743
if (buildInfoProgram) {
@@ -1783,11 +1785,12 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
17831785

17841786
// Now see if all outputs are newer than the newest input
17851787
// Dont check output timestamps if we have buildinfo telling us output is uptodate
1786-
if (!buildInfoPath) {
1788+
if (!isIncremental) {
17871789
// Collect the expected outputs of this project
17881790
const outputs = getAllProjectOutputs(project, !host.useCaseSensitiveFileNames());
17891791
const outputTimeStampMap = getOutputTimeStampMap(state, resolvedPath);
17901792
for (const output of outputs) {
1793+
if (output === buildInfoPath) continue;
17911794
const path = toPath(state, output);
17921795
// Output is missing; can stop checking
17931796
let outputTime = outputTimeStampMap?.get(path);
@@ -1921,7 +1924,8 @@ function updateOutputTimestampsWorker<T extends BuilderProgram>(
19211924
if (proj.options.noEmit) return;
19221925
let now: Date | undefined;
19231926
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(proj.options);
1924-
if (buildInfoPath) {
1927+
const isIncremental = isIncrementalCompilation(proj.options);
1928+
if (buildInfoPath && isIncremental) {
19251929
// For incremental projects, only buildinfo needs to be upto date with timestamp check
19261930
// as we dont check output files for up-to-date ness
19271931
if (!skipOutputs?.has(toPath(state, buildInfoPath))) {
@@ -1947,8 +1951,9 @@ function updateOutputTimestampsWorker<T extends BuilderProgram>(
19471951
reportStatus(state, verboseMessage, proj.options.configFilePath!);
19481952
}
19491953
host.setModifiedTime(file, now ||= getCurrentTime(state.host));
1954+
if (file === buildInfoPath) getBuildInfoCacheEntry(state, buildInfoPath, projectPath)!.modifiedTime = now;
19501955
// Store output timestamps in a map because non incremental build will need to check them to determine up-to-dateness
1951-
if (outputTimeStampMap) {
1956+
else if (outputTimeStampMap) {
19521957
outputTimeStampMap.set(path, now);
19531958
modifiedOutputs!.add(path);
19541959
}

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7372,6 +7372,7 @@ export interface CompilerOptions {
73727372
esModuleInterop?: boolean;
73737373
/** @internal */ showConfig?: boolean;
73747374
useDefineForClassFields?: boolean;
7375+
/** @internal */ tscBuild?: boolean;
73757376

73767377
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
73777378
}

src/testRunner/unittests/tsbuild/outFile.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ describe("unittests:: tsbuild:: outFile::", () => {
249249
caption: "Make non incremental build with change in file that doesnt affect dts",
250250
edit: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
251251
commandLineArgs: ["--b", "/src/third", "--verbose"],
252+
discrepancyExplanation: () => [
253+
"Clean build is non incremental so it will have non incremental tsbuildInfo for third project",
254+
"The incremental build does not build third so will only timestamps for third tsbuildInfo and hence its from incremental build before",
255+
],
252256
},
253257
{
254258
caption: "Make incremental build with change in file that doesnt affect dts",

src/testRunner/unittests/tsbuild/referencesWithRootDirInParent.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { noop } from "../../_namespaces/ts.js";
12
import { dedent } from "../../_namespaces/Utils.js";
23
import * as vfs from "../../_namespaces/vfs.js";
34
import { jsonToReadableText } from "../helpers.js";
@@ -90,6 +91,57 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
9091
edits: noChangeOnlyRuns,
9192
});
9293

94+
verifyTsc({
95+
scenario: "projectReferenceWithRootDirInParent",
96+
subScenario: "reports error for same tsbuildinfo file without incremental",
97+
fs: () => projFs,
98+
commandLineArgs: ["--b", "/src/src/main", "--verbose"],
99+
modifyFs: fs => {
100+
fs.writeFileSync(
101+
"/src/src/main/tsconfig.json",
102+
jsonToReadableText({
103+
compilerOptions: { outDir: "../../dist/" },
104+
references: [{ path: "../other" }],
105+
}),
106+
);
107+
fs.writeFileSync(
108+
"/src/src/other/tsconfig.json",
109+
jsonToReadableText({
110+
compilerOptions: { composite: true, outDir: "../../dist/" },
111+
}),
112+
);
113+
},
114+
});
115+
116+
verifyTsc({
117+
scenario: "projectReferenceWithRootDirInParent",
118+
subScenario: "reports error for same tsbuildinfo file without incremental with tsc",
119+
fs: () => projFs,
120+
commandLineArgs: ["--b", "/src/src/other", "--verbose"],
121+
modifyFs: fs => {
122+
fs.writeFileSync(
123+
"/src/src/main/tsconfig.json",
124+
jsonToReadableText({
125+
compilerOptions: { outDir: "../../dist/" },
126+
references: [{ path: "../other" }],
127+
}),
128+
);
129+
fs.writeFileSync(
130+
"/src/src/other/tsconfig.json",
131+
jsonToReadableText({
132+
compilerOptions: { composite: true, outDir: "../../dist/" },
133+
}),
134+
);
135+
},
136+
edits: [
137+
{
138+
caption: "Running tsc on main",
139+
edit: noop,
140+
commandLineArgs: ["-p", "/src/src/main"],
141+
},
142+
],
143+
});
144+
93145
verifyTsc({
94146
scenario: "projectReferenceWithRootDirInParent",
95147
subScenario: "reports no error when tsbuildinfo differ",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
error TS5069: Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or option 'composite'.
1+
error TS5111: Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or 'composite' or if not running 'tsc -b'.
22

33

4-
!!! error TS5069: Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or option 'composite'.
4+
!!! error TS5111: Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or 'composite' or if not running 'tsc -b'.
55
==== optionsTsBuildInfoFileWithoutIncrementalAndComposite.ts (0 errors) ====
66
const x = "Hello World";
77

tests/baselines/reference/tsbuild/clean/tsx-with-dts-emit.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Output::
3636
[HH:MM:SS AM] Projects in this build:
3737
* src/project/tsconfig.json
3838

39-
[[90mHH:MM:SS AM[0m] Project 'src/project/tsconfig.json' is out of date because output file 'src/project/src/main.js' does not exist
39+
[[90mHH:MM:SS AM[0m] Project 'src/project/tsconfig.json' is out of date because output file 'src/project/tsconfig.tsbuildinfo' does not exist
4040

4141
[HH:MM:SS AM] Building project '/src/project/tsconfig.json'...
4242

@@ -58,6 +58,15 @@ exports.x = void 0;
5858
exports.x = 10;
5959

6060

61+
//// [/src/project/tsconfig.tsbuildinfo]
62+
{"version":"FakeTSVersion"}
63+
64+
//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt]
65+
{
66+
"version": "FakeTSVersion",
67+
"size": 27
68+
}
69+
6170

6271

6372
Change:: no-change-run
@@ -85,5 +94,6 @@ Output::
8594
exitCode:: ExitStatus.Success
8695

8796

97+
//// [/src/project/tsconfig.tsbuildinfo] unlink
8898
//// [/src/project/src/main.d.ts] unlink
8999
//// [/src/project/src/main.js] unlink

tests/baselines/reference/tsbuild/commandLine/different-options-with-incremental-with-outFile.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Program options: {
5858
"incremental": true,
5959
"outFile": "/src/outFile.js",
6060
"module": 2,
61+
"tscBuild": true,
6162
"configFilePath": "/src/project/tsconfig.json"
6263
}
6364
Program structureReused: Not
@@ -207,6 +208,7 @@ Program options: {
207208
"outFile": "/src/outFile.js",
208209
"module": 2,
209210
"sourceMap": true,
211+
"tscBuild": true,
210212
"configFilePath": "/src/project/tsconfig.json"
211213
}
212214
Program structureReused: Not
@@ -359,6 +361,7 @@ Program options: {
359361
"incremental": true,
360362
"outFile": "/src/outFile.js",
361363
"module": 2,
364+
"tscBuild": true,
362365
"configFilePath": "/src/project/tsconfig.json"
363366
}
364367
Program structureReused: Not
@@ -508,6 +511,7 @@ Program options: {
508511
"outFile": "/src/outFile.js",
509512
"module": 2,
510513
"declaration": true,
514+
"tscBuild": true,
511515
"configFilePath": "/src/project/tsconfig.json"
512516
}
513517
Program structureReused: Not
@@ -645,6 +649,7 @@ Program options: {
645649
"module": 2,
646650
"declaration": true,
647651
"declarationMap": true,
652+
"tscBuild": true,
648653
"configFilePath": "/src/project/tsconfig.json"
649654
}
650655
Program structureReused: Not
@@ -803,6 +808,7 @@ Program options: {
803808
"incremental": true,
804809
"outFile": "/src/outFile.js",
805810
"module": 2,
811+
"tscBuild": true,
806812
"configFilePath": "/src/project/tsconfig.json"
807813
}
808814
Program structureReused: Not
@@ -953,6 +959,7 @@ Program options: {
953959
"module": 2,
954960
"declaration": true,
955961
"declarationMap": true,
962+
"tscBuild": true,
956963
"configFilePath": "/src/project/tsconfig.json"
957964
}
958965
Program structureReused: Not
@@ -1093,6 +1100,7 @@ Program options: {
10931100
"outFile": "/src/outFile.js",
10941101
"module": 2,
10951102
"inlineSourceMap": true,
1103+
"tscBuild": true,
10961104
"configFilePath": "/src/project/tsconfig.json"
10971105
}
10981106
Program structureReused: Not
@@ -1243,6 +1251,7 @@ Program options: {
12431251
"outFile": "/src/outFile.js",
12441252
"module": 2,
12451253
"sourceMap": true,
1254+
"tscBuild": true,
12461255
"configFilePath": "/src/project/tsconfig.json"
12471256
}
12481257
Program structureReused: Not
@@ -1395,6 +1404,7 @@ Program options: {
13951404
"incremental": true,
13961405
"outFile": "/src/outFile.js",
13971406
"module": 2,
1407+
"tscBuild": true,
13981408
"configFilePath": "/src/project/tsconfig.json"
13991409
}
14001410
Program structureReused: Not
@@ -1545,6 +1555,7 @@ Program options: {
15451555
"module": 2,
15461556
"declaration": true,
15471557
"declarationMap": true,
1558+
"tscBuild": true,
15481559
"configFilePath": "/src/project/tsconfig.json"
15491560
}
15501561
Program structureReused: Not

0 commit comments

Comments
 (0)