Skip to content

Commit

Permalink
Enables passing --declaration, --emitDeclarationOnly, `--declarat…
Browse files Browse the repository at this point in the history
…ionMap`, `--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
  • Loading branch information
sheetalkamat authored Nov 7, 2022
1 parent 896b922 commit eac566b
Show file tree
Hide file tree
Showing 336 changed files with 38,573 additions and 2,742 deletions.
635 changes: 355 additions & 280 deletions src/compiler/builder.ts

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/compiler/builderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ namespace ts {
export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<BuilderState>, disableUseFileVersionAsSignature?: boolean): BuilderState {
const fileInfos = new Map<Path, FileInfo>();
const options = newProgram.getCompilerOptions();
const referencedMap = options.module !== ModuleKind.None && !outFile(options) ?
const isOutFile = outFile(options);
const referencedMap = options.module !== ModuleKind.None && !isOutFile ?
createManyToManyPathMap() : undefined;
const exportedModulesMap = referencedMap ? createManyToManyPathMap() : undefined;
const useOldState = canReuseOldState(referencedMap, oldState);
Expand Down Expand Up @@ -299,7 +300,8 @@ namespace ts {
fileInfos.set(sourceFile.resolvedPath, {
version,
signature,
affectsGlobalScope: isFileAffectingGlobalScope(sourceFile) || undefined,
// No need to calculate affectsGlobalScope with --out since its not used at all
affectsGlobalScope: !isOutFile ? isFileAffectingGlobalScope(sourceFile) || undefined : undefined,
impliedFormat: sourceFile.impliedNodeFormat
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/builderStatePublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ namespace ts {
name: string;
writeByteOrderMark: boolean;
text: string;
/* @internal */ buildInfo?: BuildInfo
/* @internal */ data?: WriteFileCallbackData;
}
}
231 changes: 113 additions & 118 deletions src/compiler/commandLineParser.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -5426,6 +5426,10 @@
"category": "Message",
"code": 6405
},
"Project '{0}' is out of date because buildinfo file '{1}' indicates there is change in compilerOptions": {
"category": "Message",
"code": 6406
},

"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",
Expand Down
72 changes: 39 additions & 33 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ namespace ts {
/*@internal*/
export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: boolean): string {
if (outFile(configFile.options)) {
const { jsFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
return Debug.checkDefined(jsFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
const { jsFilePath, declarationFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
return Debug.checkDefined(jsFilePath || declarationFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
}

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

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

if (!emitSkipped && emittedFilesList) {
if (!emitOnlyDtsFiles) {
if (!emitOnly) {
if (jsFilePath) {
emittedFilesList.push(jsFilePath);
}
Expand All @@ -342,11 +342,13 @@ namespace ts {
emittedFilesList.push(buildInfoPath);
}
}
if (declarationFilePath) {
emittedFilesList.push(declarationFilePath);
}
if (declarationMapPath) {
emittedFilesList.push(declarationMapPath);
if (emitOnly !== EmitOnly.Js) {
if (declarationFilePath) {
emittedFilesList.push(declarationFilePath);
}
if (declarationMapPath) {
emittedFilesList.push(declarationMapPath);
}
}
}

Expand All @@ -358,13 +360,11 @@ namespace ts {
function emitBuildInfo(bundle: BundleBuildInfo | undefined, buildInfoPath: string | undefined) {
// Write build information if applicable
if (!buildInfoPath || targetSourceFile || emitSkipped) return;
const program = host.getProgramBuildInfo();
if (host.isEmitBlocked(buildInfoPath)) {
emitSkipped = true;
return;
}
const version = ts.version; // Extracted into a const so the form is stable between namespace and module
const buildInfo: BuildInfo = { bundle, program, version };
const buildInfo = host.getBuildInfo(bundle) || createBuildInfo(/*program*/ undefined, bundle);
// Pass buildinfo as additional data to avoid having to reparse
writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo });
}
Expand All @@ -374,7 +374,7 @@ namespace ts {
jsFilePath: string | undefined,
sourceMapFilePath: string | undefined,
relativeToBuildInfo: (path: string) => string) {
if (!sourceFileOrBundle || emitOnlyDtsFiles || !jsFilePath) {
if (!sourceFileOrBundle || emitOnly || !jsFilePath) {
return;
}

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

/*@internal*/
export function createBuildInfo(program: ProgramBuildInfo | undefined, bundle: BundleBuildInfo | undefined): BuildInfo {
const version = ts.version; // Extracted into a const so the form is stable between namespace and module
return { bundle, program, version };
}

/*@internal*/
export function getBuildInfoText(buildInfo: BuildInfo) {
return JSON.stringify(buildInfo);
Expand Down Expand Up @@ -822,21 +828,7 @@ namespace ts {
if (sourceMapText === text) return;
break;
case buildInfoPath:
const newBuildInfo = data!.buildInfo!;
newBuildInfo.program = buildInfo.program;
if (newBuildInfo.program && changedDtsText !== undefined && config.options.composite) {
// Update the output signature
(newBuildInfo.program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData);
}
// Update sourceFileInfo
const { js, dts, sourceFiles } = buildInfo.bundle!;
newBuildInfo.bundle!.js!.sources = js!.sources;
if (dts) {
newBuildInfo.bundle!.dts!.sources = dts.sources;
}
newBuildInfo.bundle!.sourceFiles = sourceFiles;
outputFiles.push({ name, text: getBuildInfoText(newBuildInfo), writeByteOrderMark, buildInfo: newBuildInfo });
return;
break;
case declarationFilePath:
if (declarationText === text) return;
changedDtsText = text;
Expand All @@ -848,13 +840,27 @@ namespace ts {
default:
Debug.fail(`Unexpected path: ${name}`);
}
outputFiles.push({ name, text, writeByteOrderMark });
outputFiles.push({ name, text, writeByteOrderMark, data });
},
isEmitBlocked: returnFalse,
readFile: f => host.readFile(f),
fileExists: f => host.fileExists(f),
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
getProgramBuildInfo: returnUndefined,
getBuildInfo: bundle => {
const program = buildInfo.program;
if (program && changedDtsText !== undefined && config.options.composite) {
// Update the output signature
(program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData);
}
// Update sourceFileInfo
const { js, dts, sourceFiles } = buildInfo.bundle!;
bundle!.js!.sources = js!.sources;
if (dts) {
bundle!.dts!.sources = dts.sources;
}
bundle!.sourceFiles = sourceFiles;
return createBuildInfo(program, bundle);
},
getSourceFileFromReference: returnUndefined,
redirectTargetsMap: createMultiMap(),
getFileIncludeReasons: notImplemented,
Expand Down
12 changes: 6 additions & 6 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1967,7 +1967,7 @@ namespace ts {
return host.fileExists(f);
},
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
getProgramBuildInfo: () => program.getProgramBuildInfo && program.getProgramBuildInfo(),
getBuildInfo: bundle => program.getBuildInfo?.(bundle),
getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref),
redirectTargetsMap,
getFileIncludeReasons: program.getFileIncludeReasons,
Expand Down Expand Up @@ -2058,9 +2058,9 @@ namespace ts {
return typeChecker || (typeChecker = createTypeChecker(program));
}

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

function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
if (!forceDtsEmit) {
const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken);
if (result) return result;
Expand All @@ -2091,8 +2091,8 @@ namespace ts {
emitResolver,
getEmitHost(writeFileCallback),
sourceFile,
getTransformers(options, customTransformers, emitOnlyDtsFiles),
emitOnlyDtsFiles,
getTransformers(options, customTransformers, emitOnly),
emitOnly,
/*onlyBuildInfo*/ false,
forceDtsEmit
);
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/sourcemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,10 @@ namespace ts {
}

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

const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
export const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;

export interface LineInfo {
getLineCount(): number;
Expand Down
8 changes: 4 additions & 4 deletions src/compiler/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ namespace ts {

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

export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers {
export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly): EmitTransformers {
return {
scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles),
scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnly),
declarationTransformers: getDeclarationTransformers(customTransformers),
};
}

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

const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/tsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace ts {
OutOfDateWithSelf,
OutOfDateWithUpstream,
OutOfDateBuildInfo,
OutOfDateOptions,
UpstreamOutOfDate,
UpstreamBlocked,
ComputingUpstream,
Expand Down Expand Up @@ -116,7 +117,7 @@ namespace ts {
* Buildinfo indicates that build is out of date
*/
export interface OutOfDateBuildInfo {
type: UpToDateStatusType.OutOfDateBuildInfo,
type: UpToDateStatusType.OutOfDateBuildInfo | UpToDateStatusType.OutOfDateOptions,
buildInfoFile: string;
}

Expand Down
Loading

0 comments on commit eac566b

Please sign in to comment.