Do not emit .js files if only d.ts file will be impacted.

This commit is contained in:
Sheetal Nandi 2019-09-10 12:53:17 -07:00
parent 11fd654cf9
commit 686e9a42db
2 changed files with 74 additions and 26 deletions

View file

@ -60,6 +60,10 @@ namespace ts {
* Files pending to be emitted
*/
affectedFilesPendingEmit?: ReadonlyArray<Path> | undefined;
/**
* Files pending to be emitted kind.
*/
affectedFilesPendingEmitKind?: ReadonlyMap<BuilderFileEmit> | undefined;
/**
* Current index to retrieve pending affected file
*/
@ -70,6 +74,11 @@ namespace ts {
hasReusableDiagnostic?: true;
}
export const enum BuilderFileEmit {
DtsOnly,
Full
}
/**
* State to store the changed files, affected files and cache semantic diagnostics
*/
@ -127,7 +136,11 @@ namespace ts {
/**
* Files pending to be emitted
*/
affectedFilesPendingEmit: ReadonlyArray<Path> | undefined;
affectedFilesPendingEmit: Path[] | undefined;
/**
* Files pending to be emitted kind.
*/
affectedFilesPendingEmitKind: Map<BuilderFileEmit> | undefined;
/**
* Current index to retrieve pending affected file
*/
@ -139,7 +152,7 @@ namespace ts {
/**
* Already seen emitted files
*/
seenEmittedFiles: Map<true> | undefined;
seenEmittedFiles: Map<BuilderFileEmit> | undefined;
/**
* true if program has been emitted
*/
@ -186,7 +199,8 @@ namespace ts {
copyEntries(changedFilesSet, state.changedFilesSet);
}
if (!compilerOptions.outFile && !compilerOptions.out && oldState!.affectedFilesPendingEmit) {
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit;
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
state.affectedFilesPendingEmitKind = cloneMapOrUndefined(oldState!.affectedFilesPendingEmitKind);
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
}
}
@ -233,7 +247,7 @@ namespace ts {
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
// Add all files to affectedFilesPendingEmit since emit changed
addToAffectedFilesPendingEmit(state, newProgram.getSourceFiles().map(f => f.path));
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.path, BuilderFileEmit.Full));
Debug.assert(state.seenAffectedFiles === undefined);
state.seenAffectedFiles = createMap<true>();
}
@ -295,7 +309,8 @@ namespace ts {
newState.semanticDiagnosticsFromOldState = cloneMapOrUndefined(state.semanticDiagnosticsFromOldState);
newState.program = state.program;
newState.compilerOptions = state.compilerOptions;
newState.affectedFilesPendingEmit = state.affectedFilesPendingEmit;
newState.affectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice();
newState.affectedFilesPendingEmitKind = cloneMapOrUndefined(state.affectedFilesPendingEmitKind);
newState.affectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex;
newState.seenEmittedFiles = cloneMapOrUndefined(state.seenEmittedFiles);
newState.programEmitComplete = state.programEmitComplete;
@ -373,19 +388,24 @@ namespace ts {
/**
* Returns next file to be emitted from files that retrieved semantic diagnostics but did not emit yet
*/
function getNextAffectedFilePendingEmit(state: BuilderProgramState): SourceFile | undefined {
function getNextAffectedFilePendingEmit(state: BuilderProgramState) {
const { affectedFilesPendingEmit } = state;
if (affectedFilesPendingEmit) {
const seenEmittedFiles = state.seenEmittedFiles || (state.seenEmittedFiles = createMap());
for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) {
const affectedFile = Debug.assertDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]);
if (affectedFile && !seenEmittedFiles.has(affectedFile.path)) {
// emit this file
state.affectedFilesPendingEmitIndex = i;
return affectedFile;
if (affectedFile) {
const seenKind = seenEmittedFiles.get(affectedFile.path);
const emitKind = Debug.assertDefined(Debug.assertDefined(state.affectedFilesPendingEmitKind).get(affectedFile.path));
if (seenKind === undefined || seenKind < emitKind) {
// emit this file
state.affectedFilesPendingEmitIndex = i;
return { affectedFile, emitKind };
}
}
}
state.affectedFilesPendingEmit = undefined;
state.affectedFilesPendingEmitKind = undefined;
state.affectedFilesPendingEmitIndex = undefined;
}
return undefined;
@ -442,7 +462,7 @@ namespace ts {
);
// If not dts emit, nothing more to do
if (getEmitDeclarations(state.compilerOptions)) {
addToAffectedFilesPendingEmit(state, [path]);
addToAffectedFilesPendingEmit(state, path, BuilderFileEmit.DtsOnly);
}
}
}
@ -548,7 +568,13 @@ namespace ts {
* This is called after completing operation on the next affected file.
* The operations here are postponed to ensure that cancellation during the iteration is handled correctly
*/
function doneWithAffectedFile(state: BuilderProgramState, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean, isEmitResult?: boolean) {
function doneWithAffectedFile(
state: BuilderProgramState,
affected: SourceFile | Program,
emitKind?: BuilderFileEmit,
isPendingEmit?: boolean,
isBuildInfoEmit?: boolean
) {
if (isBuildInfoEmit) {
state.emittedBuildInfo = true;
}
@ -558,8 +584,8 @@ namespace ts {
}
else {
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
if (isEmitResult) {
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, true);
if (emitKind !== undefined) {
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, emitKind);
}
if (isPendingEmit) {
state.affectedFilesPendingEmitIndex!++;
@ -573,16 +599,23 @@ namespace ts {
/**
* Returns the result with affected file
*/
function toAffectedFileResult<T>(state: BuilderProgramState, result: T, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean): AffectedFileResult<T> {
doneWithAffectedFile(state, affected, isPendingEmit, isBuildInfoEmit);
function toAffectedFileResult<T>(state: BuilderProgramState, result: T, affected: SourceFile | Program): AffectedFileResult<T> {
doneWithAffectedFile(state, affected);
return { result, affected };
}
/**
* Returns the result with affected file
*/
function toAffectedFileEmitResult(state: BuilderProgramState, result: EmitResult, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean): AffectedFileResult<EmitResult> {
doneWithAffectedFile(state, affected, isPendingEmit, isBuildInfoEmit, /*isEmitResult*/ true);
function toAffectedFileEmitResult(
state: BuilderProgramState,
result: EmitResult,
affected: SourceFile | Program,
emitKind: BuilderFileEmit,
isPendingEmit?: boolean,
isBuildInfoEmit?: boolean
): AffectedFileResult<EmitResult> {
doneWithAffectedFile(state, affected, emitKind, isPendingEmit, isBuildInfoEmit);
return { result, affected };
}
@ -849,11 +882,12 @@ namespace ts {
*/
function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult> {
let affected = getNextAffectedFile(state, cancellationToken, computeHash);
let emitKind = BuilderFileEmit.Full;
let isPendingEmitFile = false;
if (!affected) {
if (!state.compilerOptions.out && !state.compilerOptions.outFile) {
affected = getNextAffectedFilePendingEmit(state);
if (!affected) {
const pendingAffectedFile = getNextAffectedFilePendingEmit(state);
if (!pendingAffectedFile) {
if (state.emittedBuildInfo) {
return undefined;
}
@ -865,10 +899,12 @@ namespace ts {
// Otherwise just affected file
affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken),
affected,
/*emitKind*/ BuilderFileEmit.Full,
/*isPendingEmitFile*/ false,
/*isBuildInfoEmit*/ true
);
}
({ affectedFile: affected, emitKind } = pendingAffectedFile);
isPendingEmitFile = true;
}
else {
@ -886,10 +922,17 @@ namespace ts {
state,
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
// Otherwise just affected file
Debug.assertDefined(state.program).emit(affected === state.program ? undefined : affected as SourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers),
Debug.assertDefined(state.program).emit(
affected === state.program ? undefined : affected as SourceFile,
writeFile || maybeBind(host, host.writeFile),
cancellationToken,
emitOnlyDtsFiles || emitKind === BuilderFileEmit.DtsOnly,
customTransformers
),
affected,
emitKind,
isPendingEmitFile,
);
);
}
/**
@ -953,7 +996,7 @@ namespace ts {
// Add file to affected file pending emit to handle for later emit time
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
addToAffectedFilesPendingEmit(state, [(affected as SourceFile).path]);
addToAffectedFilesPendingEmit(state, (affected as SourceFile).path, BuilderFileEmit.Full);
}
// Get diagnostics for the affected file if its not ignored
@ -1006,8 +1049,14 @@ namespace ts {
}
}
function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilesPendingEmit: readonly Path[]) {
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, affectedFilesPendingEmit);
function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilePendingEmit: Path, kind: BuilderFileEmit) {
if (!state.affectedFilesPendingEmit) state.affectedFilesPendingEmit = [];
if (!state.affectedFilesPendingEmitKind) state.affectedFilesPendingEmitKind = createMap();
const existingKind = state.affectedFilesPendingEmitKind.get(affectedFilePendingEmit);
state.affectedFilesPendingEmit.push(affectedFilePendingEmit);
state.affectedFilesPendingEmitKind.set(affectedFilePendingEmit, existingKind || kind);
// affectedFilesPendingEmitIndex === undefined
// - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
// so start from 0 as array would be affectedFilesPendingEmit

View file

@ -26,7 +26,6 @@ import { LazyAction } from './bundling';
export declare const lazyBar: LazyAction<() => void, typeof import("./lazyIndex")>;
//// [/src/obj/index.js] file written with same contents
//// [/src/obj/lazyIndex.d.ts] file written with same contents
//// [/src/obj/lazyIndex.js] file written with same contents
//// [/src/obj/tsconfig.tsbuildinfo]