Skip to content

Commit eac566b

Browse files
authored
Enables passing --declaration, --emitDeclarationOnly, --declarationMap, --soureMap and --inlineSourceMap to tsc --build (#51241)
* Add different tests for baselining before behavior * Fix assert for first project output * Add ability to pass declaration, declarationMap, emitDeclarationOnly, sourceMap and inlineSourceMap on commandline of --build * Store these options in --out scenario * Store buildInfo program for --out even if not composite * Changes to make these commanline options work * Do not include sourceMapUrl text in the sourceFile version * Emit complete program in --out scenario as well since we need to determine uptodate ness * Copy js or dts bundle from old build if emitting only js or dts files * Dont emit dts if we want to emit only js files even though options suggest emitting d.ts files as well * Adding comments and refactoring some of the code
1 parent 896b922 commit eac566b

File tree

336 files changed

+38573
-2742
lines changed

Some content is hidden

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

336 files changed

+38573
-2742
lines changed

Diff for: src/compiler/builder.ts

+355-280
Large diffs are not rendered by default.

Diff for: src/compiler/builderState.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ namespace ts {
265265
export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<BuilderState>, disableUseFileVersionAsSignature?: boolean): BuilderState {
266266
const fileInfos = new Map<Path, FileInfo>();
267267
const options = newProgram.getCompilerOptions();
268-
const referencedMap = options.module !== ModuleKind.None && !outFile(options) ?
268+
const isOutFile = outFile(options);
269+
const referencedMap = options.module !== ModuleKind.None && !isOutFile ?
269270
createManyToManyPathMap() : undefined;
270271
const exportedModulesMap = referencedMap ? createManyToManyPathMap() : undefined;
271272
const useOldState = canReuseOldState(referencedMap, oldState);
@@ -299,7 +300,8 @@ namespace ts {
299300
fileInfos.set(sourceFile.resolvedPath, {
300301
version,
301302
signature,
302-
affectsGlobalScope: isFileAffectingGlobalScope(sourceFile) || undefined,
303+
// No need to calculate affectsGlobalScope with --out since its not used at all
304+
affectsGlobalScope: !isOutFile ? isFileAffectingGlobalScope(sourceFile) || undefined : undefined,
303305
impliedFormat: sourceFile.impliedNodeFormat
304306
});
305307
}

Diff for: src/compiler/builderStatePublic.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ namespace ts {
99
name: string;
1010
writeByteOrderMark: boolean;
1111
text: string;
12-
/* @internal */ buildInfo?: BuildInfo
12+
/* @internal */ data?: WriteFileCallbackData;
1313
}
1414
}

Diff for: src/compiler/commandLineParser.ts

+113-118
Large diffs are not rendered by default.

Diff for: src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -5426,6 +5426,10 @@
54265426
"category": "Message",
54275427
"code": 6405
54285428
},
5429+
"Project '{0}' is out of date because buildinfo file '{1}' indicates there is change in compilerOptions": {
5430+
"category": "Message",
5431+
"code": 6406
5432+
},
54295433

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

Diff for: src/compiler/emitter.ts

+39-33
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ namespace ts {
257257
/*@internal*/
258258
export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: boolean): string {
259259
if (outFile(configFile.options)) {
260-
const { jsFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
261-
return Debug.checkDefined(jsFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
260+
const { jsFilePath, declarationFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
261+
return Debug.checkDefined(jsFilePath || declarationFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
262262
}
263263

264264
const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase));
@@ -278,7 +278,7 @@ namespace ts {
278278

279279
/*@internal*/
280280
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
281-
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnlyDtsFiles?: boolean, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult {
281+
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnly?: boolean | EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult {
282282
const compilerOptions = host.getCompilerOptions();
283283
const sourceMapDataList: SourceMapEmitResult[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined;
284284
const emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined;
@@ -331,7 +331,7 @@ namespace ts {
331331
tracing?.pop();
332332

333333
if (!emitSkipped && emittedFilesList) {
334-
if (!emitOnlyDtsFiles) {
334+
if (!emitOnly) {
335335
if (jsFilePath) {
336336
emittedFilesList.push(jsFilePath);
337337
}
@@ -342,11 +342,13 @@ namespace ts {
342342
emittedFilesList.push(buildInfoPath);
343343
}
344344
}
345-
if (declarationFilePath) {
346-
emittedFilesList.push(declarationFilePath);
347-
}
348-
if (declarationMapPath) {
349-
emittedFilesList.push(declarationMapPath);
345+
if (emitOnly !== EmitOnly.Js) {
346+
if (declarationFilePath) {
347+
emittedFilesList.push(declarationFilePath);
348+
}
349+
if (declarationMapPath) {
350+
emittedFilesList.push(declarationMapPath);
351+
}
350352
}
351353
}
352354

@@ -358,13 +360,11 @@ namespace ts {
358360
function emitBuildInfo(bundle: BundleBuildInfo | undefined, buildInfoPath: string | undefined) {
359361
// Write build information if applicable
360362
if (!buildInfoPath || targetSourceFile || emitSkipped) return;
361-
const program = host.getProgramBuildInfo();
362363
if (host.isEmitBlocked(buildInfoPath)) {
363364
emitSkipped = true;
364365
return;
365366
}
366-
const version = ts.version; // Extracted into a const so the form is stable between namespace and module
367-
const buildInfo: BuildInfo = { bundle, program, version };
367+
const buildInfo = host.getBuildInfo(bundle) || createBuildInfo(/*program*/ undefined, bundle);
368368
// Pass buildinfo as additional data to avoid having to reparse
369369
writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo });
370370
}
@@ -374,7 +374,7 @@ namespace ts {
374374
jsFilePath: string | undefined,
375375
sourceMapFilePath: string | undefined,
376376
relativeToBuildInfo: (path: string) => string) {
377-
if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) {
377+
if (!sourceFileOrBundle || emitOnly || !jsFilePath) {
378378
return;
379379
}
380380

@@ -424,16 +424,16 @@ namespace ts {
424424
declarationFilePath: string | undefined,
425425
declarationMapPath: string | undefined,
426426
relativeToBuildInfo: (path: string) => string) {
427-
if (!sourceFileOrBundle) return;
427+
if (!sourceFileOrBundle || emitOnly === EmitOnly.Js) return;
428428
if (!declarationFilePath) {
429-
if (emitOnlyDtsFiles || compilerOptions.emitDeclarationOnly) emitSkipped = true;
429+
if (emitOnly || compilerOptions.emitDeclarationOnly) emitSkipped = true;
430430
return;
431431
}
432432
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
433433
const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson);
434434
// Setup and perform the transformation to retrieve declarations from the input files
435435
const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
436-
if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) {
436+
if (emitOnly && !getEmitDeclarations(compilerOptions)) {
437437
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
438438
// Do that here when emitting only dts files
439439
filesForEmit.forEach(collectLinkedAliases);
@@ -646,6 +646,12 @@ namespace ts {
646646
}
647647
}
648648

649+
/*@internal*/
650+
export function createBuildInfo(program: ProgramBuildInfo | undefined, bundle: BundleBuildInfo | undefined): BuildInfo {
651+
const version = ts.version; // Extracted into a const so the form is stable between namespace and module
652+
return { bundle, program, version };
653+
}
654+
649655
/*@internal*/
650656
export function getBuildInfoText(buildInfo: BuildInfo) {
651657
return JSON.stringify(buildInfo);
@@ -822,21 +828,7 @@ namespace ts {
822828
if (sourceMapText === text) return;
823829
break;
824830
case buildInfoPath:
825-
const newBuildInfo = data!.buildInfo!;
826-
newBuildInfo.program = buildInfo.program;
827-
if (newBuildInfo.program && changedDtsText !== undefined && config.options.composite) {
828-
// Update the output signature
829-
(newBuildInfo.program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData);
830-
}
831-
// Update sourceFileInfo
832-
const { js, dts, sourceFiles } = buildInfo.bundle!;
833-
newBuildInfo.bundle!.js!.sources = js!.sources;
834-
if (dts) {
835-
newBuildInfo.bundle!.dts!.sources = dts.sources;
836-
}
837-
newBuildInfo.bundle!.sourceFiles = sourceFiles;
838-
outputFiles.push({ name, text: getBuildInfoText(newBuildInfo), writeByteOrderMark, buildInfo: newBuildInfo });
839-
return;
831+
break;
840832
case declarationFilePath:
841833
if (declarationText === text) return;
842834
changedDtsText = text;
@@ -848,13 +840,27 @@ namespace ts {
848840
default:
849841
Debug.fail(`Unexpected path: ${name}`);
850842
}
851-
outputFiles.push({ name, text, writeByteOrderMark });
843+
outputFiles.push({ name, text, writeByteOrderMark, data });
852844
},
853845
isEmitBlocked: returnFalse,
854846
readFile: f => host.readFile(f),
855847
fileExists: f => host.fileExists(f),
856848
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
857-
getProgramBuildInfo: returnUndefined,
849+
getBuildInfo: bundle => {
850+
const program = buildInfo.program;
851+
if (program && changedDtsText !== undefined && config.options.composite) {
852+
// Update the output signature
853+
(program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData);
854+
}
855+
// Update sourceFileInfo
856+
const { js, dts, sourceFiles } = buildInfo.bundle!;
857+
bundle!.js!.sources = js!.sources;
858+
if (dts) {
859+
bundle!.dts!.sources = dts.sources;
860+
}
861+
bundle!.sourceFiles = sourceFiles;
862+
return createBuildInfo(program, bundle);
863+
},
858864
getSourceFileFromReference: returnUndefined,
859865
redirectTargetsMap: createMultiMap(),
860866
getFileIncludeReasons: notImplemented,

Diff for: src/compiler/program.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,7 @@ namespace ts {
19671967
return host.fileExists(f);
19681968
},
19691969
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
1970-
getProgramBuildInfo: () => program.getProgramBuildInfo && program.getProgramBuildInfo(),
1970+
getBuildInfo: bundle => program.getBuildInfo?.(bundle),
19711971
getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref),
19721972
redirectTargetsMap,
19731973
getFileIncludeReasons: program.getFileIncludeReasons,
@@ -2058,9 +2058,9 @@ namespace ts {
20582058
return typeChecker || (typeChecker = createTypeChecker(program));
20592059
}
20602060

2061-
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
2061+
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
20622062
tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true);
2063-
const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, forceDtsEmit));
2063+
const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit));
20642064
tracing?.pop();
20652065
return result;
20662066
}
@@ -2069,7 +2069,7 @@ namespace ts {
20692069
return hasEmitBlockingDiagnostics.has(toPath(emitFileName));
20702070
}
20712071

2072-
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
2072+
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
20732073
if (!forceDtsEmit) {
20742074
const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken);
20752075
if (result) return result;
@@ -2091,8 +2091,8 @@ namespace ts {
20912091
emitResolver,
20922092
getEmitHost(writeFileCallback),
20932093
sourceFile,
2094-
getTransformers(options, customTransformers, emitOnlyDtsFiles),
2095-
emitOnlyDtsFiles,
2094+
getTransformers(options, customTransformers, emitOnly),
2095+
emitOnly,
20962096
/*onlyBuildInfo*/ false,
20972097
forceDtsEmit
20982098
);

Diff for: src/compiler/sourcemap.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,10 @@ namespace ts {
322322
}
323323

324324
// Sometimes tools can see the following line as a source mapping url comment, so we mangle it a bit (the [M])
325-
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/;
325+
export const sourceMapCommentRegExpDontCareLineStart = /\/\/[@#] source[M]appingURL=(.+)\r?\n?$/;
326+
export const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/;
326327

327-
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
328+
export const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
328329

329330
export interface LineInfo {
330331
getLineCount(): number;

Diff for: src/compiler/transformer.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ namespace ts {
3131

3232
export const noTransformers: EmitTransformers = { scriptTransformers: emptyArray, declarationTransformers: emptyArray };
3333

34-
export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers {
34+
export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly): EmitTransformers {
3535
return {
36-
scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles),
36+
scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnly),
3737
declarationTransformers: getDeclarationTransformers(customTransformers),
3838
};
3939
}
4040

41-
function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) {
42-
if (emitOnlyDtsFiles) return emptyArray;
41+
function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly) {
42+
if (emitOnly) return emptyArray;
4343

4444
const languageVersion = getEmitScriptTarget(compilerOptions);
4545
const moduleKind = getEmitModuleKind(compilerOptions);

Diff for: src/compiler/tsbuild.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace ts {
2020
OutOfDateWithSelf,
2121
OutOfDateWithUpstream,
2222
OutOfDateBuildInfo,
23+
OutOfDateOptions,
2324
UpstreamOutOfDate,
2425
UpstreamBlocked,
2526
ComputingUpstream,
@@ -116,7 +117,7 @@ namespace ts {
116117
* Buildinfo indicates that build is out of date
117118
*/
118119
export interface OutOfDateBuildInfo {
119-
type: UpToDateStatusType.OutOfDateBuildInfo,
120+
type: UpToDateStatusType.OutOfDateBuildInfo | UpToDateStatusType.OutOfDateOptions,
120121
buildInfoFile: string;
121122
}
122123

0 commit comments

Comments
 (0)