Skip to content

Commit 9edddc7

Browse files
authored
Write buildInfo even if we dont emit js or dts for --outFile scenarios (#58760)
1 parent afad099 commit 9edddc7

File tree

97 files changed

+10299
-1018
lines changed

Some content is hidden

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

97 files changed

+10299
-1018
lines changed

src/compiler/builder.ts

+183-96
Large diffs are not rendered by default.

src/compiler/emitter.ts

+29-22
Original file line numberDiff line numberDiff line change
@@ -453,28 +453,28 @@ export function forEachEmittedFile<T>(
453453
) {
454454
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit);
455455
const options = host.getCompilerOptions();
456-
if (options.outFile) {
457-
if (sourceFiles.length) {
458-
const bundle = factory.createBundle(sourceFiles);
459-
const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle);
460-
if (result) {
461-
return result;
456+
if (!onlyBuildInfo) {
457+
if (options.outFile) {
458+
if (sourceFiles.length) {
459+
const bundle = factory.createBundle(sourceFiles);
460+
const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle);
461+
if (result) {
462+
return result;
463+
}
462464
}
463465
}
464-
}
465-
else {
466-
if (!onlyBuildInfo) {
466+
else {
467467
for (const sourceFile of sourceFiles) {
468468
const result = action(getOutputPathsFor(sourceFile, host, forceDtsEmit), sourceFile);
469469
if (result) {
470470
return result;
471471
}
472472
}
473473
}
474-
if (includeBuildInfo) {
475-
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options);
476-
if (buildInfoPath) return action({ buildInfoPath }, /*sourceFileOrBundle*/ undefined);
477-
}
474+
}
475+
if (includeBuildInfo) {
476+
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options);
477+
if (buildInfoPath) return action({ buildInfoPath }, /*sourceFileOrBundle*/ undefined);
478478
}
479479
}
480480

@@ -506,8 +506,7 @@ export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths:
506506
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
507507
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined;
508508
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
509-
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options);
510-
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath };
509+
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath };
511510
}
512511

513512
/** @internal */
@@ -526,7 +525,7 @@ export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHos
526525
const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
527526
const declarationFilePath = (forceDtsPaths || (getEmitDeclarations(options) && !isJsonFile)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
528527
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
529-
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined };
528+
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath };
530529
}
531530
}
532531

@@ -601,12 +600,11 @@ function createAddOutput() {
601600
}
602601

603602
function getSingleOutputFileNames(configFile: ParsedCommandLine, addOutput: ReturnType<typeof createAddOutput>["addOutput"]) {
604-
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
603+
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
605604
addOutput(jsFilePath);
606605
addOutput(sourceMapFilePath);
607606
addOutput(declarationFilePath);
608607
addOutput(declarationMapPath);
609-
addOutput(buildInfoPath);
610608
}
611609

612610
function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType<typeof createAddOutput>["addOutput"], getCommonSourceDirectory?: () => string) {
@@ -679,8 +677,8 @@ export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase:
679677
for (const inputFileName of configFile.fileNames) {
680678
getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput, getCommonSourceDirectory);
681679
}
682-
addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options));
683680
}
681+
addOutput(getTsBuildInfoEmitOutputFilePath(configFile.options));
684682
return getOutputs();
685683
}
686684

@@ -726,7 +724,16 @@ export function emitResolverSkipsTypeChecking(emitOnly: boolean | EmitOnly | und
726724

727725
/** @internal */
728726
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
729-
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnly?: boolean | EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult {
727+
export function emitFiles(
728+
resolver: EmitResolver,
729+
host: EmitHost,
730+
targetSourceFile: SourceFile | undefined,
731+
{ scriptTransformers, declarationTransformers }: EmitTransformers,
732+
emitOnly: boolean | EmitOnly | undefined,
733+
onlyBuildInfo: boolean,
734+
forceDtsEmit?: boolean,
735+
skipBuildInfo?: boolean,
736+
): EmitResult {
730737
// Why var? It avoids TDZ checks in the runtime which can be costly.
731738
// See: https://github.com/microsoft/TypeScript/issues/52924
732739
/* eslint-disable no-var */
@@ -748,7 +755,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
748755
getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit),
749756
forceDtsEmit,
750757
onlyBuildInfo,
751-
!targetSourceFile,
758+
!targetSourceFile && !skipBuildInfo,
752759
);
753760
exit();
754761

@@ -775,7 +782,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
775782

776783
function emitBuildInfo(buildInfoPath: string | undefined) {
777784
// Write build information if applicable
778-
if (!buildInfoPath || targetSourceFile || emitSkipped) return;
785+
if (!buildInfoPath || targetSourceFile) return;
779786
if (host.isEmitBlocked(buildInfoPath)) {
780787
emitSkipped = true;
781788
return;

src/compiler/program.ts

+34-6
Original file line numberDiff line numberDiff line change
@@ -2788,7 +2788,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
27882788
}
27892789

27902790
function emitBuildInfo(writeFileCallback?: WriteFileCallback): EmitResult {
2791-
Debug.assert(!options.outFile);
27922791
tracing?.push(tracing.Phase.Emit, "emitBuildInfo", {}, /*separateBeginAndEnd*/ true);
27932792
performance.mark("beforeEmit");
27942793
const emitResult = emitFiles(
@@ -2846,9 +2845,28 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
28462845
return typeChecker || (typeChecker = createTypeChecker(program));
28472846
}
28482847

2849-
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
2848+
function emit(
2849+
sourceFile?: SourceFile,
2850+
writeFileCallback?: WriteFileCallback,
2851+
cancellationToken?: CancellationToken,
2852+
emitOnly?: boolean | EmitOnly,
2853+
transformers?: CustomTransformers,
2854+
forceDtsEmit?: boolean,
2855+
skipBuildInfo?: boolean,
2856+
): EmitResult {
28502857
tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true);
2851-
const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit));
2858+
const result = runWithCancellationToken(() =>
2859+
emitWorker(
2860+
program,
2861+
sourceFile,
2862+
writeFileCallback,
2863+
cancellationToken,
2864+
emitOnly,
2865+
transformers,
2866+
forceDtsEmit,
2867+
skipBuildInfo,
2868+
)
2869+
);
28522870
tracing?.pop();
28532871
return result;
28542872
}
@@ -2857,7 +2875,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
28572875
return hasEmitBlockingDiagnostics.has(toPath(emitFileName));
28582876
}
28592877

2860-
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
2878+
function emitWorker(
2879+
program: Program,
2880+
sourceFile: SourceFile | undefined,
2881+
writeFileCallback: WriteFileCallback | undefined,
2882+
cancellationToken: CancellationToken | undefined,
2883+
emitOnly: boolean | EmitOnly | undefined,
2884+
customTransformers: CustomTransformers | undefined,
2885+
forceDtsEmit: boolean | undefined,
2886+
skipBuildInfo: boolean | undefined,
2887+
): EmitResult {
28612888
if (!forceDtsEmit) {
28622889
const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken);
28632890
if (result) return result;
@@ -2891,6 +2918,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
28912918
emitOnly,
28922919
/*onlyBuildInfo*/ false,
28932920
forceDtsEmit,
2921+
skipBuildInfo,
28942922
),
28952923
);
28962924

@@ -5410,7 +5438,7 @@ export function handleNoEmitOptions<T extends BuilderProgram>(
54105438
if (options.noEmit) {
54115439
// Cache the semantic diagnostics
54125440
program.getSemanticDiagnostics(sourceFile, cancellationToken);
5413-
return sourceFile || options.outFile ?
5441+
return sourceFile ?
54145442
emitSkippedWithNoDiagnostics :
54155443
program.emitBuildInfo(writeFile, cancellationToken);
54165444
}
@@ -5432,7 +5460,7 @@ export function handleNoEmitOptions<T extends BuilderProgram>(
54325460

54335461
if (!diagnostics.length) return undefined;
54345462
let emittedFiles: string[] | undefined;
5435-
if (!sourceFile && !options.outFile) {
5463+
if (!sourceFile) {
54365464
const emitResult = program.emitBuildInfo(writeFile, cancellationToken);
54375465
if (emitResult.diagnostics) diagnostics = [...diagnostics, ...emitResult.diagnostics];
54385466
emittedFiles = emitResult.emittedFiles;

src/compiler/tsbuildPublic.ts

+6-17
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ import {
9090
PollingInterval,
9191
Program,
9292
ProgramBuildInfo,
93+
ProgramBundleEmitBuildInfo,
9394
ProgramHost,
9495
ProgramMultiFileEmitBuildInfo,
9596
ProgramUpdateLevel,
@@ -1074,8 +1075,6 @@ function createBuildOrUpdateInvalidedProject<T extends BuilderProgram>(
10741075
({ buildResult, step } = buildErrors(
10751076
state,
10761077
projectPath,
1077-
program,
1078-
config,
10791078
diagnostics,
10801079
errorFlags,
10811080
errorType,
@@ -1132,8 +1131,6 @@ function createBuildOrUpdateInvalidedProject<T extends BuilderProgram>(
11321131
({ buildResult, step } = buildErrors(
11331132
state,
11341133
projectPath,
1135-
program,
1136-
config,
11371134
declDiagnostics,
11381135
BuildResultFlags.DeclarationEmitErrors,
11391136
"Declaration file",
@@ -1208,8 +1205,6 @@ function createBuildOrUpdateInvalidedProject<T extends BuilderProgram>(
12081205
({ buildResult, step } = buildErrors(
12091206
state,
12101207
projectPath,
1211-
program,
1212-
config,
12131208
emitDiagnostics,
12141209
BuildResultFlags.EmitErrors,
12151210
"Emit",
@@ -1453,20 +1448,13 @@ function afterProgramDone<T extends BuilderProgram>(
14531448
function buildErrors<T extends BuilderProgram>(
14541449
state: SolutionBuilderState<T>,
14551450
resolvedPath: ResolvedConfigFilePath,
1456-
program: T | undefined,
1457-
config: ParsedCommandLine,
14581451
diagnostics: readonly Diagnostic[],
14591452
buildResult: BuildResultFlags,
14601453
errorType: string,
14611454
) {
1462-
// 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-
14651455
reportAndStoreErrors(state, resolvedPath, diagnostics);
14661456
state.projectStatus.set(resolvedPath, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
1467-
if (canEmitBuildInfo) return { buildResult, step: BuildStep.EmitBuildInfo };
1468-
afterProgramDone(state, program);
1469-
return { buildResult, step: BuildStep.QueueReferencingProjects };
1457+
return { buildResult, step: BuildStep.EmitBuildInfo };
14701458
}
14711459

14721460
function isFileWatcherWithModifiedTime(value: FileWatcherWithModifiedTime | Date): value is FileWatcherWithModifiedTime {
@@ -1692,11 +1680,12 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
16921680
// 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
16931681
// 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
16941682
if (
1695-
(buildInfo.program as ProgramMultiFileEmitBuildInfo).changeFileSet?.length ||
1683+
buildInfo.program.changeFileSet?.length ||
16961684
(!project.options.noEmit ?
16971685
(buildInfo.program as ProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length ||
1698-
(buildInfo.program as ProgramMultiFileEmitBuildInfo).emitDiagnosticsPerFile?.length :
1699-
(buildInfo.program as ProgramMultiFileEmitBuildInfo).semanticDiagnosticsPerFile?.length)
1686+
buildInfo.program.emitDiagnosticsPerFile?.length ||
1687+
(buildInfo.program as ProgramBundleEmitBuildInfo).pendingEmit !== undefined :
1688+
buildInfo.program.semanticDiagnosticsPerFile?.length)
17001689
) {
17011690
return {
17021691
type: UpToDateStatusType.OutOfDateBuildInfo,

src/compiler/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4707,7 +4707,7 @@ export interface Program extends ScriptReferenceHost {
47074707
*/
47084708
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
47094709
/** @internal */
4710-
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult;
4710+
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean, skipBuildInfo?: boolean): EmitResult;
47114711

47124712
getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
47134713
getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];

0 commit comments

Comments
 (0)