mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 11:24:49 -05:00
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
This commit is contained in:
@@ -20,6 +20,9 @@ namespace ts {
|
||||
|
||||
export type ReusableDiagnosticMessageChain = DiagnosticMessageChain;
|
||||
|
||||
/** Signature (Hash of d.ts emitted), is string if it was emitted using same d.ts.map option as what compilerOptions indicate, otherwise tuple of string */
|
||||
export type EmitSignature = string | [signature: string];
|
||||
|
||||
export interface ReusableBuilderProgramState extends BuilderState {
|
||||
/**
|
||||
* Cache of bind and check diagnostics for files with their Path being the key
|
||||
@@ -40,15 +43,11 @@ namespace ts {
|
||||
/**
|
||||
* Files pending to be emitted
|
||||
*/
|
||||
affectedFilesPendingEmit?: readonly Path[] | undefined;
|
||||
affectedFilesPendingEmit?: ReadonlyESMap<Path, BuilderFileEmit>;
|
||||
/**
|
||||
* Files pending to be emitted kind.
|
||||
* emitKind pending for a program with --out
|
||||
*/
|
||||
affectedFilesPendingEmitKind?: ESMap<Path, BuilderFileEmit> | undefined;
|
||||
/**
|
||||
* Current index to retrieve pending affected file
|
||||
*/
|
||||
affectedFilesPendingEmitIndex?: number | undefined;
|
||||
programEmitPending?: BuilderFileEmit;
|
||||
/*
|
||||
* true if semantic diagnostics are ReusableDiagnostic instead of Diagnostic
|
||||
*/
|
||||
@@ -56,20 +55,32 @@ namespace ts {
|
||||
/**
|
||||
* Hash of d.ts emitted for the file, use to track when emit of d.ts changes
|
||||
*/
|
||||
emitSignatures?: ESMap<Path, string>;
|
||||
emitSignatures?: ESMap<Path, EmitSignature>;
|
||||
/**
|
||||
* Hash of d.ts emit with --out
|
||||
*/
|
||||
outSignature?: string;
|
||||
outSignature?: EmitSignature;
|
||||
/**
|
||||
* Name of the file whose dts was the latest to change
|
||||
*/
|
||||
latestChangedDtsFile: string | undefined;
|
||||
/**
|
||||
* Bundle information either from oldState or current one so it can be used to complete the information in buildInfo when emitting only js or dts files
|
||||
*/
|
||||
bundle?: BundleBuildInfo;
|
||||
}
|
||||
|
||||
export const enum BuilderFileEmit {
|
||||
DtsOnly,
|
||||
Full
|
||||
None = 0,
|
||||
Js = 1 << 0, // emit js file
|
||||
JsMap = 1 << 1, // emit js.map file
|
||||
JsInlineMap = 1 << 2, // emit inline source map in js file
|
||||
Dts = 1 << 3, // emit d.ts file
|
||||
DtsMap = 1 << 4, // emit d.ts.map file
|
||||
|
||||
AllJs = Js | JsMap | JsInlineMap,
|
||||
AllDts = Dts | DtsMap,
|
||||
All = AllJs | AllDts,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +127,7 @@ namespace ts {
|
||||
/**
|
||||
* Files pending to be emitted
|
||||
*/
|
||||
affectedFilesPendingEmit: Path[] | undefined;
|
||||
affectedFilesPendingEmit?: ESMap<Path, BuilderFileEmit>;
|
||||
/**
|
||||
* true if build info is emitted
|
||||
*/
|
||||
@@ -125,26 +136,46 @@ namespace ts {
|
||||
* Already seen emitted files
|
||||
*/
|
||||
seenEmittedFiles: ESMap<Path, BuilderFileEmit> | undefined;
|
||||
/**
|
||||
* true if program has been emitted
|
||||
*/
|
||||
programEmitComplete?: true;
|
||||
/** Stores list of files that change signature during emit - test only */
|
||||
filesChangingSignature?: Set<Path>;
|
||||
}
|
||||
|
||||
export type SavedBuildProgramEmitState = Pick<BuilderProgramState,
|
||||
"affectedFilesPendingEmit" |
|
||||
"affectedFilesPendingEmitIndex" |
|
||||
"affectedFilesPendingEmitKind" |
|
||||
"seenEmittedFiles" |
|
||||
"programEmitComplete" |
|
||||
"programEmitPending" |
|
||||
"emitSignatures" |
|
||||
"outSignature" |
|
||||
"latestChangedDtsFile" |
|
||||
"hasChangedEmitSignature"
|
||||
> & { changedFilesSet: BuilderProgramState["changedFilesSet"] | undefined };
|
||||
|
||||
/** Get flags determining what all needs to be emitted */
|
||||
export function getBuilderFileEmit(options: CompilerOptions) {
|
||||
let result = BuilderFileEmit.Js;
|
||||
if (options.sourceMap) result = result | BuilderFileEmit.JsMap;
|
||||
if (options.inlineSourceMap) result = result | BuilderFileEmit.JsInlineMap;
|
||||
if (getEmitDeclarations(options)) result = result | BuilderFileEmit.Dts;
|
||||
if (options.declarationMap) result = result | BuilderFileEmit.DtsMap;
|
||||
if (options.emitDeclarationOnly) result = result & BuilderFileEmit.AllDts;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Determing what all is pending to be emitted based on previous options or previous file emit flags */
|
||||
export function getPendingEmitKind(optionsOrEmitKind: CompilerOptions | BuilderFileEmit, oldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined): BuilderFileEmit {
|
||||
const oldEmitKind = oldOptionsOrEmitKind && (isNumber(oldOptionsOrEmitKind) ? oldOptionsOrEmitKind : getBuilderFileEmit(oldOptionsOrEmitKind));
|
||||
const emitKind = isNumber(optionsOrEmitKind) ? optionsOrEmitKind : getBuilderFileEmit(optionsOrEmitKind);
|
||||
if (oldEmitKind === emitKind) return BuilderFileEmit.None;
|
||||
if (!oldEmitKind || !emitKind) return emitKind;
|
||||
const diff = oldEmitKind ^ emitKind;
|
||||
let result = BuilderFileEmit.None;
|
||||
// If there is diff in Js emit, pending emit is js emit flags
|
||||
if (diff & BuilderFileEmit.AllJs) result = emitKind & BuilderFileEmit.AllJs;
|
||||
// If there is diff in Dts emit, pending emit is dts emit flags
|
||||
if (diff & BuilderFileEmit.AllDts) result = result | (emitKind & BuilderFileEmit.AllDts);
|
||||
return result;
|
||||
}
|
||||
|
||||
function hasSameKeys(map1: ReadonlyCollection<string> | undefined, map2: ReadonlyCollection<string> | undefined): boolean {
|
||||
// Has same size and every key is present in both maps
|
||||
return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key));
|
||||
@@ -164,7 +195,7 @@ namespace ts {
|
||||
state.semanticDiagnosticsPerFile = new Map();
|
||||
}
|
||||
else if (compilerOptions.composite && oldState?.outSignature && outFilePath === outFile(oldState?.compilerOptions)) {
|
||||
state.outSignature = oldState?.outSignature;
|
||||
state.outSignature = oldState.outSignature && getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldState.outSignature);
|
||||
}
|
||||
state.changedFilesSet = new Set();
|
||||
state.latestChangedDtsFile = compilerOptions.composite ? oldState?.latestChangedDtsFile : undefined;
|
||||
@@ -186,12 +217,15 @@ namespace ts {
|
||||
if (useOldState) {
|
||||
// Copy old state's changed files set
|
||||
oldState!.changedFilesSet?.forEach(value => state.changedFilesSet.add(value));
|
||||
if (!outFilePath && oldState!.affectedFilesPendingEmit) {
|
||||
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
|
||||
state.affectedFilesPendingEmitKind = oldState!.affectedFilesPendingEmitKind && new Map(oldState!.affectedFilesPendingEmitKind);
|
||||
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
|
||||
if (!outFilePath && oldState!.affectedFilesPendingEmit?.size) {
|
||||
state.affectedFilesPendingEmit = new Map(oldState!.affectedFilesPendingEmit);
|
||||
state.seenAffectedFiles = new Set();
|
||||
}
|
||||
state.programEmitPending = oldState!.programEmitPending;
|
||||
}
|
||||
else {
|
||||
// We arent using old state, so atleast emit buildInfo with current information
|
||||
state.buildInfoEmitPending = true;
|
||||
}
|
||||
|
||||
// Update changed files and copy semantic diagnostics if we can
|
||||
@@ -216,7 +250,7 @@ namespace ts {
|
||||
// Referenced file was deleted in the new program
|
||||
newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) {
|
||||
// Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated
|
||||
state.changedFilesSet.add(sourceFilePath);
|
||||
addFileToChangeSet(state, sourceFilePath);
|
||||
}
|
||||
else if (canCopySemanticDiagnostics) {
|
||||
const sourceFile = newProgram.getSourceFileByPath(sourceFilePath)!;
|
||||
@@ -236,26 +270,75 @@ namespace ts {
|
||||
}
|
||||
if (canCopyEmitSignatures) {
|
||||
const oldEmitSignature = oldState.emitSignatures.get(sourceFilePath);
|
||||
if (oldEmitSignature) (state.emitSignatures ||= new Map()).set(sourceFilePath, oldEmitSignature);
|
||||
if (oldEmitSignature) {
|
||||
(state.emitSignatures ??= new Map()).set(sourceFilePath, getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldEmitSignature));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If the global file is removed, add all files as changed
|
||||
if (useOldState && forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => info.affectsGlobalScope && !state.fileInfos.has(sourceFilePath))) {
|
||||
if (useOldState && forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => (outFilePath || info.affectsGlobalScope) && !state.fileInfos.has(sourceFilePath))) {
|
||||
BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined)
|
||||
.forEach(file => state.changedFilesSet.add(file.resolvedPath));
|
||||
.forEach(file => addFileToChangeSet(state, file.resolvedPath));
|
||||
}
|
||||
else if (oldCompilerOptions && !outFilePath && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
|
||||
// Add all files to affectedFilesPendingEmit since emit changed
|
||||
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
|
||||
Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size);
|
||||
state.seenAffectedFiles = state.seenAffectedFiles || new Set();
|
||||
else if (oldCompilerOptions) {
|
||||
// If options affect emit, then we need to do complete emit per compiler options
|
||||
// otherwise only the js or dts that needs to emitted because its different from previously emitted options
|
||||
const pendingEmitKind = compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions) ?
|
||||
getBuilderFileEmit(compilerOptions) :
|
||||
getPendingEmitKind(compilerOptions, oldCompilerOptions);
|
||||
if (pendingEmitKind !== BuilderFileEmit.None) {
|
||||
if (!outFilePath) {
|
||||
// Add all files to affectedFilesPendingEmit since emit changed
|
||||
newProgram.getSourceFiles().forEach(f => {
|
||||
// Add to affectedFilesPending emit only if not changed since any changed file will do full emit
|
||||
if (!state.changedFilesSet.has(f.resolvedPath)) {
|
||||
addToAffectedFilesPendingEmit(
|
||||
state,
|
||||
f.resolvedPath,
|
||||
pendingEmitKind
|
||||
);
|
||||
}
|
||||
});
|
||||
Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size);
|
||||
state.seenAffectedFiles = state.seenAffectedFiles || new Set();
|
||||
state.buildInfoEmitPending = true;
|
||||
}
|
||||
else {
|
||||
state.programEmitPending = state.programEmitPending ?
|
||||
state.programEmitPending | pendingEmitKind :
|
||||
pendingEmitKind;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outFilePath && !state.changedFilesSet.size) {
|
||||
// Copy the bundle information from old state so we can patch it later if we are doing partial emit
|
||||
if (useOldState) state.bundle = oldState!.bundle;
|
||||
// If this program has prepend references, always emit since we wont know if files on disk are correct unless we check file hash for correctness
|
||||
if (some(newProgram.getProjectReferences(), ref => !!ref.prepend)) state.programEmitPending = getBuilderFileEmit(compilerOptions);
|
||||
}
|
||||
// Since old states change files set is copied, any additional change means we would need to emit build info
|
||||
state.buildInfoEmitPending = !useOldState || state.changedFilesSet.size !== (oldState!.changedFilesSet?.size || 0);
|
||||
return state;
|
||||
}
|
||||
|
||||
function addFileToChangeSet(state: BuilderProgramState, path: Path) {
|
||||
state.changedFilesSet.add(path);
|
||||
state.buildInfoEmitPending = true;
|
||||
// Setting this to undefined as changed files means full emit so no need to track emit explicitly
|
||||
state.programEmitPending = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Covert to Emit signature based on oldOptions and EmitSignature format
|
||||
* If d.ts map options differ then swap the format, otherwise use as is
|
||||
*/
|
||||
function getEmitSignatureFromOldSignature(options: CompilerOptions, oldOptions: CompilerOptions, oldEmitSignature: EmitSignature): EmitSignature {
|
||||
return !!options.declarationMap === !!oldOptions.declarationMap ?
|
||||
// Use same format of signature
|
||||
oldEmitSignature :
|
||||
// Convert to different format
|
||||
isString(oldEmitSignature) ? [oldEmitSignature] : oldEmitSignature[0];
|
||||
}
|
||||
|
||||
function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newProgram: Program, getCanonicalFileName: GetCanonicalFileName): readonly Diagnostic[] {
|
||||
if (!diagnostics.length) return emptyArray;
|
||||
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory()));
|
||||
@@ -300,11 +383,9 @@ namespace ts {
|
||||
// Only in --out changeFileSet is kept around till emit
|
||||
Debug.assert(!state.changedFilesSet.size || outFilePath);
|
||||
return {
|
||||
affectedFilesPendingEmit: state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(),
|
||||
affectedFilesPendingEmitKind: state.affectedFilesPendingEmitKind && new Map(state.affectedFilesPendingEmitKind),
|
||||
affectedFilesPendingEmitIndex: state.affectedFilesPendingEmitIndex,
|
||||
affectedFilesPendingEmit: state.affectedFilesPendingEmit && new Map(state.affectedFilesPendingEmit),
|
||||
seenEmittedFiles: state.seenEmittedFiles && new Map(state.seenEmittedFiles),
|
||||
programEmitComplete: state.programEmitComplete,
|
||||
programEmitPending: state.programEmitPending,
|
||||
emitSignatures: state.emitSignatures && new Map(state.emitSignatures),
|
||||
outSignature: state.outSignature,
|
||||
latestChangedDtsFile: state.latestChangedDtsFile,
|
||||
@@ -315,10 +396,8 @@ namespace ts {
|
||||
|
||||
function restoreBuilderProgramEmitState(state: BuilderProgramState, savedEmitState: SavedBuildProgramEmitState) {
|
||||
state.affectedFilesPendingEmit = savedEmitState.affectedFilesPendingEmit;
|
||||
state.affectedFilesPendingEmitKind = savedEmitState.affectedFilesPendingEmitKind;
|
||||
state.affectedFilesPendingEmitIndex = savedEmitState.affectedFilesPendingEmitIndex;
|
||||
state.seenEmittedFiles = savedEmitState.seenEmittedFiles;
|
||||
state.programEmitComplete = savedEmitState.programEmitComplete;
|
||||
state.programEmitPending = savedEmitState.programEmitPending;
|
||||
state.emitSignatures = savedEmitState.emitSignatures;
|
||||
state.outSignature = savedEmitState.outSignature;
|
||||
state.latestChangedDtsFile = savedEmitState.latestChangedDtsFile;
|
||||
@@ -356,6 +435,7 @@ namespace ts {
|
||||
if (!seenAffectedFiles.has(affectedFile.resolvedPath)) {
|
||||
// Set the next affected file as seen and remove the cached semantic diagnostics
|
||||
state.affectedFilesIndex = affectedFilesIndex;
|
||||
addToAffectedFilesPendingEmit(state, affectedFile.resolvedPath, getBuilderFileEmit(state.compilerOptions));
|
||||
handleDtsMayChangeOfAffectedFile(
|
||||
state,
|
||||
affectedFile,
|
||||
@@ -409,34 +489,33 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function clearAffectedFilesPendingEmit(state: BuilderProgramState) {
|
||||
state.affectedFilesPendingEmit = undefined;
|
||||
state.affectedFilesPendingEmitKind = undefined;
|
||||
state.affectedFilesPendingEmitIndex = undefined;
|
||||
function clearAffectedFilesPendingEmit(state: BuilderProgramState, emitOnlyDtsFiles: boolean | undefined) {
|
||||
if (!state.affectedFilesPendingEmit?.size) return;
|
||||
if (!emitOnlyDtsFiles) return state.affectedFilesPendingEmit = undefined;
|
||||
state.affectedFilesPendingEmit.forEach((emitKind, path) => {
|
||||
// Mark the files as pending only if they are pending on js files, remove the dts emit pending flag
|
||||
const pending = emitKind & BuilderFileEmit.AllJs;
|
||||
if (!pending) state.affectedFilesPendingEmit!.delete(path);
|
||||
else state.affectedFilesPendingEmit!.set(path, pending);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next file to be emitted from files that retrieved semantic diagnostics but did not emit yet
|
||||
*/
|
||||
function getNextAffectedFilePendingEmit(state: BuilderProgramState) {
|
||||
const { affectedFilesPendingEmit } = state;
|
||||
if (affectedFilesPendingEmit) {
|
||||
const seenEmittedFiles = (state.seenEmittedFiles || (state.seenEmittedFiles = new Map()));
|
||||
for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) {
|
||||
const affectedFile = Debug.checkDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]);
|
||||
if (affectedFile && sourceFileMayBeEmitted(affectedFile, state.program!)) {
|
||||
const seenKind = seenEmittedFiles.get(affectedFile.resolvedPath);
|
||||
const emitKind = Debug.checkDefined(Debug.checkDefined(state.affectedFilesPendingEmitKind).get(affectedFile.resolvedPath));
|
||||
if (seenKind === undefined || seenKind < emitKind) {
|
||||
// emit this file
|
||||
state.affectedFilesPendingEmitIndex = i;
|
||||
return { affectedFile, emitKind };
|
||||
}
|
||||
}
|
||||
function getNextAffectedFilePendingEmit(state: BuilderProgramState, emitOnlyDtsFiles: boolean | undefined) {
|
||||
if (!state.affectedFilesPendingEmit?.size) return undefined;
|
||||
return forEachEntry(state.affectedFilesPendingEmit, (emitKind, path) => {
|
||||
const affectedFile = state.program!.getSourceFileByPath(path);
|
||||
if (!affectedFile || !sourceFileMayBeEmitted(affectedFile, state.program!)) {
|
||||
state.affectedFilesPendingEmit!.delete(path);
|
||||
return undefined;
|
||||
}
|
||||
clearAffectedFilesPendingEmit(state);
|
||||
}
|
||||
return undefined;
|
||||
const seenKind = state.seenEmittedFiles?.get(affectedFile.resolvedPath);
|
||||
let pendingKind = getPendingEmitKind(emitKind, seenKind);
|
||||
if (emitOnlyDtsFiles) pendingKind = pendingKind & BuilderFileEmit.AllDts;
|
||||
if (pendingKind) return { affectedFile, emitKind: pendingKind };
|
||||
});
|
||||
}
|
||||
|
||||
function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) {
|
||||
@@ -527,7 +606,7 @@ namespace ts {
|
||||
);
|
||||
// If not dts emit, nothing more to do
|
||||
if (getEmitDeclarations(state.compilerOptions)) {
|
||||
addToAffectedFilesPendingEmit(state, path, BuilderFileEmit.DtsOnly);
|
||||
addToAffectedFilesPendingEmit(state, path, state.compilerOptions.declarationMap ? BuilderFileEmit.AllDts : BuilderFileEmit.Dts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -677,63 +756,6 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
emitKind?: BuilderFileEmit,
|
||||
isPendingEmit?: boolean,
|
||||
isBuildInfoEmit?: boolean
|
||||
) {
|
||||
if (isBuildInfoEmit) {
|
||||
state.buildInfoEmitPending = false;
|
||||
}
|
||||
else if (affected === state.program) {
|
||||
state.changedFilesSet.clear();
|
||||
state.programEmitComplete = true;
|
||||
}
|
||||
else {
|
||||
state.seenAffectedFiles!.add((affected as SourceFile).resolvedPath);
|
||||
// Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted
|
||||
state.buildInfoEmitPending = true;
|
||||
if (emitKind !== undefined) {
|
||||
(state.seenEmittedFiles || (state.seenEmittedFiles = new Map())).set((affected as SourceFile).resolvedPath, emitKind);
|
||||
}
|
||||
if (isPendingEmit) {
|
||||
state.affectedFilesPendingEmitIndex!++;
|
||||
}
|
||||
else {
|
||||
state.affectedFilesIndex!++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result with affected file
|
||||
*/
|
||||
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,
|
||||
emitKind: BuilderFileEmit,
|
||||
isPendingEmit?: boolean,
|
||||
isBuildInfoEmit?: boolean
|
||||
): AffectedFileResult<EmitResult> {
|
||||
doneWithAffectedFile(state, affected, emitKind, isPendingEmit, isBuildInfoEmit);
|
||||
return { result, affected };
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets semantic diagnostics for the file which are
|
||||
* bindAndCheckDiagnostics (from cache) and program diagnostics
|
||||
@@ -770,9 +792,14 @@ namespace ts {
|
||||
export type ProgramBuildInfoFileId = number & { __programBuildInfoFileIdBrand: any };
|
||||
export type ProgramBuildInfoFileIdListId = number & { __programBuildInfoFileIdListIdBrand: any };
|
||||
export type ProgramBuildInfoDiagnostic = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId, diagnostics: readonly ReusableDiagnostic[]];
|
||||
export type ProgramBuilderInfoFilePendingEmit = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId];
|
||||
/**
|
||||
* fileId if pending emit is same as what compilerOptions suggest
|
||||
* [fileId] if pending emit is only dts file emit
|
||||
* [fileId, emitKind] if any other type emit is pending
|
||||
*/
|
||||
export type ProgramBuilderInfoFilePendingEmit = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId] | [fileId: ProgramBuildInfoFileId, emitKind: BuilderFileEmit];
|
||||
export type ProgramBuildInfoReferencedMap = [fileId: ProgramBuildInfoFileId, fileIdListId: ProgramBuildInfoFileIdListId][];
|
||||
export type ProgramBuildInfoBuilderStateFileInfo = Omit<BuilderState.FileInfo, "signature"> & {
|
||||
export type ProgramMultiFileEmitBuildInfoBuilderStateFileInfo = Omit<BuilderState.FileInfo, "signature"> & {
|
||||
/**
|
||||
* Signature is
|
||||
* - undefined if FileInfo.version === FileInfo.signature
|
||||
@@ -785,14 +812,14 @@ namespace ts {
|
||||
* [fileId, signature] if different from file's signature
|
||||
* fileId if file wasnt emitted
|
||||
*/
|
||||
export type ProgramBuildInfoEmitSignature = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId, signature: string];
|
||||
export type ProgramBuildInfoEmitSignature = ProgramBuildInfoFileId | [fileId: ProgramBuildInfoFileId, signature: EmitSignature | []];
|
||||
/**
|
||||
* ProgramBuildInfoFileInfo is string if FileInfo.version === FileInfo.signature && !FileInfo.affectsGlobalScope otherwise encoded FileInfo
|
||||
* ProgramMultiFileEmitBuildInfoFileInfo is string if FileInfo.version === FileInfo.signature && !FileInfo.affectsGlobalScope otherwise encoded FileInfo
|
||||
*/
|
||||
export type ProgramBuildInfoFileInfo = string | ProgramBuildInfoBuilderStateFileInfo;
|
||||
export type ProgramMultiFileEmitBuildInfoFileInfo = string | ProgramMultiFileEmitBuildInfoBuilderStateFileInfo;
|
||||
export interface ProgramMultiFileEmitBuildInfo {
|
||||
fileNames: readonly string[];
|
||||
fileInfos: readonly ProgramBuildInfoFileInfo[];
|
||||
fileInfos: readonly ProgramMultiFileEmitBuildInfoFileInfo[];
|
||||
options: CompilerOptions | undefined;
|
||||
fileIdsList: readonly (readonly ProgramBuildInfoFileId[])[] | undefined;
|
||||
referencedMap: ProgramBuildInfoReferencedMap | undefined;
|
||||
@@ -804,13 +831,22 @@ namespace ts {
|
||||
// Because this is only output file in the program, we dont need fileId to deduplicate name
|
||||
latestChangedDtsFile?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* ProgramBundleEmitBuildInfoFileInfo is string if !FileInfo.impliedFormat otherwise encoded FileInfo
|
||||
*/
|
||||
export type ProgramBundleEmitBuildInfoFileInfo = string | BuilderState.FileInfo;
|
||||
/**
|
||||
* false if it is the emit corresponding to compilerOptions
|
||||
* value otherwise
|
||||
*/
|
||||
export type ProgramBuildInfoBundlePendingEmit = BuilderFileEmit | false;
|
||||
export interface ProgramBundleEmitBuildInfo {
|
||||
fileNames: readonly string[];
|
||||
fileInfos: readonly string[];
|
||||
fileInfos: readonly ProgramBundleEmitBuildInfoFileInfo[];
|
||||
options: CompilerOptions | undefined;
|
||||
outSignature: string | undefined;
|
||||
outSignature: EmitSignature | undefined;
|
||||
latestChangedDtsFile: string | undefined;
|
||||
pendingEmit: ProgramBuildInfoBundlePendingEmit | undefined;
|
||||
}
|
||||
|
||||
export type ProgramBuildInfo = ProgramMultiFileEmitBuildInfo | ProgramBundleEmitBuildInfo;
|
||||
@@ -822,38 +858,50 @@ namespace ts {
|
||||
/**
|
||||
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
|
||||
*/
|
||||
function getProgramBuildInfo(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
|
||||
const outFilePath = outFile(state.compilerOptions);
|
||||
if (outFilePath && !state.compilerOptions.composite) return;
|
||||
function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName, bundle: BundleBuildInfo | undefined): BuildInfo {
|
||||
const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory();
|
||||
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory));
|
||||
// Convert the file name to Path here if we set the fileName instead to optimize multiple d.ts file emits and having to compute Canonical path
|
||||
const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : undefined;
|
||||
if (outFilePath) {
|
||||
const fileNames: string[] = [];
|
||||
const fileInfos: string[] = [];
|
||||
state.program!.getRootFileNames().forEach(f => {
|
||||
const sourceFile = state.program!.getSourceFile(f);
|
||||
if (!sourceFile) return;
|
||||
fileNames.push(relativeToBuildInfo(sourceFile.resolvedPath));
|
||||
fileInfos.push(sourceFile.version);
|
||||
});
|
||||
const result: ProgramBundleEmitBuildInfo = {
|
||||
fileNames,
|
||||
fileInfos,
|
||||
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions, "affectsBundleEmitBuildInfo"),
|
||||
outSignature: state.outSignature,
|
||||
latestChangedDtsFile,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
const fileNames: string[] = [];
|
||||
const fileNameToFileId = new Map<string, ProgramBuildInfoFileId>();
|
||||
if (outFile(state.compilerOptions)) {
|
||||
// Copy all fileInfo, version and impliedFormat
|
||||
// Affects global scope and signature doesnt matter because with --out they arent calculated or needed to determine upto date ness
|
||||
const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => {
|
||||
// Ensure fileId
|
||||
toFileId(key);
|
||||
return value.impliedFormat ?
|
||||
{ version: value.version, impliedFormat: value.impliedFormat, signature: undefined, affectsGlobalScope: undefined } :
|
||||
value.version;
|
||||
});
|
||||
const program: ProgramBundleEmitBuildInfo = {
|
||||
fileNames,
|
||||
fileInfos,
|
||||
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions),
|
||||
outSignature: state.outSignature,
|
||||
latestChangedDtsFile,
|
||||
pendingEmit: !state.programEmitPending ?
|
||||
undefined : // Pending is undefined or None is encoded as undefined
|
||||
state.programEmitPending === getBuilderFileEmit(state.compilerOptions) ?
|
||||
false : // Pending emit is same as deteremined by compilerOptions
|
||||
state.programEmitPending, // Actual value
|
||||
};
|
||||
// Complete the bundle information if we are doing partial emit (only js or only dts)
|
||||
const { js, dts, commonSourceDirectory, sourceFiles } = bundle!;
|
||||
state.bundle = bundle = {
|
||||
commonSourceDirectory,
|
||||
sourceFiles,
|
||||
js: js || (!state.compilerOptions.emitDeclarationOnly ? state.bundle?.js : undefined),
|
||||
dts: dts || (getEmitDeclarations(state.compilerOptions) ? state.bundle?.dts : undefined),
|
||||
};
|
||||
return createBuildInfo(program, bundle);
|
||||
}
|
||||
|
||||
let fileIdsList: (readonly ProgramBuildInfoFileId[])[] | undefined;
|
||||
let fileNamesToFileIdListId: ESMap<string, ProgramBuildInfoFileIdListId> | undefined;
|
||||
let emitSignatures: ProgramBuildInfoEmitSignature[] | undefined;
|
||||
const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBuildInfoFileInfo => {
|
||||
const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => {
|
||||
// Ensure fileId
|
||||
const fileId = toFileId(key);
|
||||
Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key));
|
||||
@@ -864,7 +912,10 @@ namespace ts {
|
||||
if (!isJsonSourceFile(file) && sourceFileMayBeEmitted(file, state.program!)) {
|
||||
const emitSignature = state.emitSignatures?.get(key);
|
||||
if (emitSignature !== actualSignature) {
|
||||
(emitSignatures ||= []).push(emitSignature === undefined ? fileId : [fileId, emitSignature]);
|
||||
(emitSignatures ||= []).push(emitSignature === undefined ?
|
||||
fileId : // There is no emit, encode as false
|
||||
// fileId, signature: emptyArray if signature only differs in dtsMap option than our own compilerOptions otherwise EmitSignature
|
||||
[fileId, !isString(emitSignature) && emitSignature[0] === actualSignature ? emptyArray as [] : emitSignature]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -919,15 +970,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
let affectedFilesPendingEmit: ProgramBuilderInfoFilePendingEmit[] | undefined;
|
||||
if (state.affectedFilesPendingEmit) {
|
||||
if (state.affectedFilesPendingEmit?.size) {
|
||||
const fullEmitForOptions = getBuilderFileEmit(state.compilerOptions);
|
||||
const seenFiles = new Set<Path>();
|
||||
for (const path of state.affectedFilesPendingEmit.slice(state.affectedFilesPendingEmitIndex).sort(compareStringsCaseSensitive)) {
|
||||
for (const path of arrayFrom(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) {
|
||||
if (tryAddToSet(seenFiles, path)) {
|
||||
const file = state.program!.getSourceFileByPath(path)!;
|
||||
if (!sourceFileMayBeEmitted(file, state.program!)) continue;
|
||||
const fileId = toFileId(path), emitKind = state.affectedFilesPendingEmitKind!.get(path)!;
|
||||
const fileId = toFileId(path), pendingEmit = state.affectedFilesPendingEmit.get(path)!;
|
||||
(affectedFilesPendingEmit ||= []).push(
|
||||
emitKind === BuilderFileEmit.Full ? fileId : [fileId]
|
||||
pendingEmit === fullEmitForOptions ?
|
||||
fileId : // Pending full emit per options
|
||||
pendingEmit === BuilderFileEmit.Dts ?
|
||||
[fileId] : // Pending on Dts only
|
||||
[fileId, pendingEmit] // Anything else
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -940,10 +996,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const result: ProgramMultiFileEmitBuildInfo = {
|
||||
const program: ProgramMultiFileEmitBuildInfo = {
|
||||
fileNames,
|
||||
fileInfos,
|
||||
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions, "affectsMultiFileEmitBuildInfo"),
|
||||
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions),
|
||||
fileIdsList,
|
||||
referencedMap,
|
||||
exportedModulesMap,
|
||||
@@ -953,7 +1009,7 @@ namespace ts {
|
||||
emitSignatures,
|
||||
latestChangedDtsFile,
|
||||
};
|
||||
return result;
|
||||
return createBuildInfo(program, bundle);
|
||||
|
||||
function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
|
||||
return relativeToBuildInfo(getNormalizedAbsolutePath(path, currentDirectory));
|
||||
@@ -986,12 +1042,12 @@ namespace ts {
|
||||
/**
|
||||
* @param optionKey key of CommandLineOption to use to determine if the option should be serialized in tsbuildinfo
|
||||
*/
|
||||
function convertToProgramBuildInfoCompilerOptions(options: CompilerOptions, optionKey: "affectsBundleEmitBuildInfo" | "affectsMultiFileEmitBuildInfo") {
|
||||
function convertToProgramBuildInfoCompilerOptions(options: CompilerOptions) {
|
||||
let result: CompilerOptions | undefined;
|
||||
const { optionsNameMap } = getOptionsNameMap();
|
||||
for (const name of getOwnKeys(options).sort(compareStringsCaseSensitive)) {
|
||||
const optionInfo = optionsNameMap.get(name.toLowerCase());
|
||||
if (optionInfo?.[optionKey]) {
|
||||
if (optionInfo?.affectsBuildInfo) {
|
||||
(result ||= {})[name] = convertToReusableCompilerOptionValue(
|
||||
optionInfo,
|
||||
options[name] as CompilerOptionsValue,
|
||||
@@ -1149,7 +1205,7 @@ namespace ts {
|
||||
*/
|
||||
const computeHash = maybeBind(host, host.createHash);
|
||||
const state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState, host.disableUseFileVersionAsSignature);
|
||||
newProgram.getProgramBuildInfo = () => getProgramBuildInfo(state, getCanonicalFileName);
|
||||
newProgram.getBuildInfo = bundle => getBuildInfo(state, getCanonicalFileName, bundle);
|
||||
|
||||
// To ensure that we arent storing any references to old program or new program without state
|
||||
newProgram = undefined!; // TODO: GH#18217
|
||||
@@ -1197,58 +1253,76 @@ namespace ts {
|
||||
*/
|
||||
function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult> {
|
||||
let affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host);
|
||||
let emitKind = BuilderFileEmit.Full;
|
||||
let isPendingEmitFile = false;
|
||||
const programEmitKind = getBuilderFileEmit(state.compilerOptions);
|
||||
let emitKind: BuilderFileEmit = emitOnlyDtsFiles ?
|
||||
programEmitKind & BuilderFileEmit.AllDts : programEmitKind;
|
||||
if (!affected) {
|
||||
if (!outFile(state.compilerOptions)) {
|
||||
const pendingAffectedFile = getNextAffectedFilePendingEmit(state);
|
||||
const pendingAffectedFile = getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles);
|
||||
if (!pendingAffectedFile) {
|
||||
if (!state.buildInfoEmitPending) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const affected = Debug.checkDefined(state.program);
|
||||
return toAffectedFileEmitResult(
|
||||
state,
|
||||
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
||||
// Otherwise just affected file
|
||||
affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken),
|
||||
affected,
|
||||
/*emitKind*/ BuilderFileEmit.Full,
|
||||
/*isPendingEmitFile*/ false,
|
||||
/*isBuildInfoEmit*/ true
|
||||
);
|
||||
// Emit buildinfo if pending
|
||||
if (!state.buildInfoEmitPending) return undefined;
|
||||
const affected = state.program!;
|
||||
const result = affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken);
|
||||
state.buildInfoEmitPending = false;
|
||||
return { result, affected };
|
||||
}
|
||||
// Emit pending affected file
|
||||
({ affectedFile: affected, emitKind } = pendingAffectedFile);
|
||||
isPendingEmitFile = true;
|
||||
}
|
||||
else {
|
||||
const program = Debug.checkDefined(state.program);
|
||||
if (state.programEmitComplete) return undefined;
|
||||
affected = program;
|
||||
// Emit program if it was pending emit
|
||||
if (!state.programEmitPending) return undefined;
|
||||
emitKind = state.programEmitPending;
|
||||
if (emitOnlyDtsFiles) emitKind = emitKind & BuilderFileEmit.AllDts;
|
||||
if (!emitKind) return undefined;
|
||||
affected = state.program!;
|
||||
}
|
||||
}
|
||||
|
||||
return toAffectedFileEmitResult(
|
||||
state,
|
||||
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
||||
// Otherwise just affected file
|
||||
Debug.checkDefined(state.program).emit(
|
||||
affected === state.program ? undefined : affected as SourceFile,
|
||||
getEmitDeclarations(state.compilerOptions) ?
|
||||
getWriteFileCallback(writeFile, customTransformers) :
|
||||
writeFile || maybeBind(host, host.writeFile),
|
||||
cancellationToken,
|
||||
emitOnlyDtsFiles || emitKind === BuilderFileEmit.DtsOnly,
|
||||
customTransformers
|
||||
),
|
||||
affected,
|
||||
emitKind,
|
||||
isPendingEmitFile,
|
||||
// Determine if we can do partial emit
|
||||
let emitOnly: EmitOnly | undefined;
|
||||
if (emitKind & BuilderFileEmit.AllJs) emitOnly = EmitOnly.Js;
|
||||
if (emitKind & BuilderFileEmit.AllDts) emitOnly = emitOnly === undefined ? EmitOnly.Dts : undefined;
|
||||
if (affected === state.program) {
|
||||
// Set up programEmit before calling emit so that its set in buildInfo
|
||||
state.programEmitPending = state.changedFilesSet.size ?
|
||||
getPendingEmitKind(programEmitKind, emitKind) :
|
||||
state.programEmitPending ?
|
||||
getPendingEmitKind(state.programEmitPending, emitKind) :
|
||||
undefined;
|
||||
}
|
||||
// Actual emit
|
||||
const result = state.program!.emit(
|
||||
affected === state.program ? undefined : affected as SourceFile,
|
||||
getWriteFileCallback(writeFile, customTransformers),
|
||||
cancellationToken,
|
||||
emitOnly,
|
||||
customTransformers
|
||||
);
|
||||
if (affected !== state.program) {
|
||||
// update affected files
|
||||
const affectedSourceFile = affected as SourceFile;
|
||||
state.seenAffectedFiles!.add(affectedSourceFile.resolvedPath);
|
||||
if (state.affectedFilesIndex !== undefined) state.affectedFilesIndex++;
|
||||
// Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted
|
||||
state.buildInfoEmitPending = true;
|
||||
// Update the pendingEmit for the file
|
||||
const existing = state.seenEmittedFiles?.get(affectedSourceFile.resolvedPath) || BuilderFileEmit.None;
|
||||
(state.seenEmittedFiles ??= new Map()).set(affectedSourceFile.resolvedPath, emitKind | existing);
|
||||
const existingPending = state.affectedFilesPendingEmit?.get(affectedSourceFile.resolvedPath) || programEmitKind;
|
||||
const pendingKind = getPendingEmitKind(existingPending, emitKind | existing);
|
||||
if (pendingKind) (state.affectedFilesPendingEmit ??= new Map()).set(affectedSourceFile.resolvedPath, pendingKind);
|
||||
else state.affectedFilesPendingEmit?.delete(affectedSourceFile.resolvedPath);
|
||||
}
|
||||
else {
|
||||
// In program clear our changed files since any emit handles all changes
|
||||
state.changedFilesSet.clear();
|
||||
}
|
||||
return { result, affected };
|
||||
}
|
||||
|
||||
function getWriteFileCallback(writeFile: WriteFileCallback | undefined, customTransformers: CustomTransformers | undefined): WriteFileCallback {
|
||||
function getWriteFileCallback(writeFile: WriteFileCallback | undefined, customTransformers: CustomTransformers | undefined): WriteFileCallback | undefined {
|
||||
if (!getEmitDeclarations(state.compilerOptions)) return writeFile || maybeBind(host, host.writeFile);
|
||||
return (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
|
||||
if (isDeclarationFileName(fileName)) {
|
||||
if (!outFile(state.compilerOptions)) {
|
||||
@@ -1290,27 +1364,43 @@ namespace ts {
|
||||
// and would need their d.ts change time in --build mode
|
||||
if (state.compilerOptions.composite) {
|
||||
const filePath = sourceFiles[0].resolvedPath;
|
||||
const oldSignature = state.emitSignatures?.get(filePath);
|
||||
emitSignature ??= computeSignature(text, computeHash, data);
|
||||
// Dont write dts files if they didn't change
|
||||
if (emitSignature === oldSignature) return;
|
||||
emitSignature = handleNewSignature(state.emitSignatures?.get(filePath), emitSignature);
|
||||
if (!emitSignature) return;
|
||||
(state.emitSignatures ??= new Map()).set(filePath, emitSignature);
|
||||
state.hasChangedEmitSignature = true;
|
||||
state.latestChangedDtsFile = fileName;
|
||||
}
|
||||
}
|
||||
else if (state.compilerOptions.composite) {
|
||||
const newSignature = computeSignature(text, computeHash, data);
|
||||
// Dont write dts files if they didn't change
|
||||
if (newSignature === state.outSignature) return;
|
||||
const newSignature = handleNewSignature(state.outSignature, /*newSignature*/ undefined);
|
||||
if (!newSignature) return;
|
||||
state.outSignature = newSignature;
|
||||
state.hasChangedEmitSignature = true;
|
||||
state.latestChangedDtsFile = fileName;
|
||||
}
|
||||
}
|
||||
if (writeFile) writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
||||
else if (host.writeFile) host.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
||||
else state.program!.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data);
|
||||
|
||||
/**
|
||||
* Compare to existing computed signature and store it or handle the changes in d.ts map option from before
|
||||
* returning undefined means that, we dont need to emit this d.ts file since its contents didnt change
|
||||
*/
|
||||
function handleNewSignature(oldSignatureFormat: EmitSignature | undefined, newSignature: string | undefined) {
|
||||
const oldSignature = !oldSignatureFormat || isString(oldSignatureFormat) ? oldSignatureFormat : oldSignatureFormat[0];
|
||||
newSignature ??= computeSignature(text, computeHash, data);
|
||||
// Dont write dts files if they didn't change
|
||||
if (newSignature === oldSignature) {
|
||||
// If the signature was encoded as string the dts map options match so nothing to do
|
||||
if (oldSignatureFormat === oldSignature) return undefined;
|
||||
// Mark as differsOnlyInMap so that --build can reverse the timestamp so that
|
||||
// the downstream projects dont detect this as change in d.ts file
|
||||
else if (data) data.differsOnlyInMap = true;
|
||||
else data = { differsOnlyInMap: true };
|
||||
}
|
||||
else {
|
||||
state.hasChangedEmitSignature = true;
|
||||
state.latestChangedDtsFile = fileName;
|
||||
}
|
||||
return newSignature;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1356,23 +1446,13 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
// In non Emit builder, clear affected files pending emit
|
||||
else if (state.affectedFilesPendingEmitKind?.size) {
|
||||
Debug.assert(kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram);
|
||||
// State can clear affected files pending emit if
|
||||
if (!emitOnlyDtsFiles // If we are doing complete emit, affected files pending emit can be cleared
|
||||
// If every file pending emit is pending on only dts emit
|
||||
|| every(state.affectedFilesPendingEmit, (path, index) =>
|
||||
index < state.affectedFilesPendingEmitIndex! ||
|
||||
state.affectedFilesPendingEmitKind!.get(path) === BuilderFileEmit.DtsOnly)) {
|
||||
clearAffectedFilesPendingEmit(state);
|
||||
}
|
||||
else {
|
||||
clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles);
|
||||
}
|
||||
}
|
||||
return Debug.checkDefined(state.program).emit(
|
||||
targetSourceFile,
|
||||
getEmitDeclarations(state.compilerOptions) ?
|
||||
getWriteFileCallback(writeFile, customTransformers) :
|
||||
writeFile || maybeBind(host, host.writeFile),
|
||||
getWriteFileCallback(writeFile, customTransformers),
|
||||
cancellationToken,
|
||||
emitOnlyDtsFiles,
|
||||
customTransformers
|
||||
@@ -1386,37 +1466,27 @@ namespace ts {
|
||||
function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult<readonly Diagnostic[]> {
|
||||
while (true) {
|
||||
const affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host);
|
||||
if (!affected) {
|
||||
// Done
|
||||
return undefined;
|
||||
let result;
|
||||
if (!affected) return undefined; // Done
|
||||
else if (affected !== state.program) {
|
||||
// Get diagnostics for the affected file if its not ignored
|
||||
const affectedSourceFile = affected as SourceFile;
|
||||
if (!ignoreSourceFile || !ignoreSourceFile(affectedSourceFile)) {
|
||||
result = getSemanticDiagnosticsOfFile(state, affectedSourceFile, cancellationToken);
|
||||
}
|
||||
state.seenAffectedFiles!.add(affectedSourceFile.resolvedPath);
|
||||
state.affectedFilesIndex!++;
|
||||
// Change in changeSet, buildInfo needs to be emitted
|
||||
state.buildInfoEmitPending = true;
|
||||
if (!result) continue;
|
||||
}
|
||||
else if (affected === state.program) {
|
||||
else {
|
||||
// When whole program is affected, get all semantic diagnostics (eg when --out or --outFile is specified)
|
||||
return toAffectedFileResult(
|
||||
state,
|
||||
state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken),
|
||||
affected
|
||||
);
|
||||
result = state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken);
|
||||
state.changedFilesSet.clear();
|
||||
state.programEmitPending = getBuilderFileEmit(state.compilerOptions);
|
||||
}
|
||||
|
||||
// Add file to affected file pending emit to handle for later emit time
|
||||
// Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters
|
||||
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) {
|
||||
addToAffectedFilesPendingEmit(state, (affected as SourceFile).resolvedPath, BuilderFileEmit.Full);
|
||||
}
|
||||
|
||||
// Get diagnostics for the affected file if its not ignored
|
||||
if (ignoreSourceFile && ignoreSourceFile(affected as SourceFile)) {
|
||||
// Get next affected file
|
||||
doneWithAffectedFile(state, affected);
|
||||
continue;
|
||||
}
|
||||
|
||||
return toAffectedFileResult(
|
||||
state,
|
||||
getSemanticDiagnosticsOfFile(state, affected as SourceFile, cancellationToken),
|
||||
affected
|
||||
);
|
||||
return { result, affected };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,23 +1526,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilePendingEmit: Path, kind: BuilderFileEmit) {
|
||||
if (!state.affectedFilesPendingEmit) state.affectedFilesPendingEmit = [];
|
||||
if (!state.affectedFilesPendingEmitKind) state.affectedFilesPendingEmitKind = new Map();
|
||||
|
||||
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
|
||||
// else, continue to iterate from existing index, the current set is appended to existing files
|
||||
if (state.affectedFilesPendingEmitIndex === undefined) {
|
||||
state.affectedFilesPendingEmitIndex = 0;
|
||||
}
|
||||
const existingKind = state.affectedFilesPendingEmit?.get(affectedFilePendingEmit) || BuilderFileEmit.None;
|
||||
(state.affectedFilesPendingEmit ??= new Map()).set(affectedFilePendingEmit, existingKind | kind);
|
||||
}
|
||||
|
||||
export function toBuilderStateFileInfo(fileInfo: ProgramBuildInfoFileInfo): BuilderState.FileInfo {
|
||||
export function toBuilderStateFileInfoForMultiEmit(fileInfo: ProgramMultiFileEmitBuildInfoFileInfo): BuilderState.FileInfo {
|
||||
return isString(fileInfo) ?
|
||||
{ version: fileInfo, signature: fileInfo, affectsGlobalScope: undefined, impliedFormat: undefined } :
|
||||
isString(fileInfo.signature) ?
|
||||
@@ -1480,41 +1538,60 @@ namespace ts {
|
||||
{ version: fileInfo.version, signature: fileInfo.signature === false ? undefined : fileInfo.version, affectsGlobalScope: fileInfo.affectsGlobalScope, impliedFormat: fileInfo.impliedFormat };
|
||||
}
|
||||
|
||||
export function toBuilderFileEmit(value: ProgramBuilderInfoFilePendingEmit): BuilderFileEmit{
|
||||
return isNumber(value) ? BuilderFileEmit.Full : BuilderFileEmit.DtsOnly;
|
||||
export function toBuilderFileEmit(value: ProgramBuilderInfoFilePendingEmit, fullEmitForOptions: BuilderFileEmit): BuilderFileEmit{
|
||||
return isNumber(value) ? fullEmitForOptions : value[1] || BuilderFileEmit.Dts;
|
||||
}
|
||||
|
||||
export function createBuilderProgramUsingProgramBuildInfo(program: ProgramBuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram {
|
||||
export function toProgramEmitPending(value: ProgramBuildInfoBundlePendingEmit, options: CompilerOptions | undefined): BuilderFileEmit | undefined {
|
||||
return !value ? getBuilderFileEmit(options || {}) : value;
|
||||
}
|
||||
|
||||
export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram {
|
||||
const program = buildInfo.program!;
|
||||
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory()));
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
|
||||
let state: ReusableBuilderProgramState;
|
||||
let filePaths: Path[] | undefined;
|
||||
const filePaths = program.fileNames?.map(toPath);
|
||||
let filePathsSetList: Set<Path>[] | undefined;
|
||||
const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) : undefined;
|
||||
if (isProgramBundleEmitBuildInfo(program)) {
|
||||
const fileInfos = new Map<Path, BuilderState.FileInfo>();
|
||||
program.fileInfos.forEach((fileInfo, index) => {
|
||||
const path = toFilePath(index + 1 as ProgramBuildInfoFileId);
|
||||
fileInfos.set(path, isString(fileInfo) ? { version: fileInfo, signature: undefined, affectsGlobalScope: undefined, impliedFormat: undefined } : fileInfo);
|
||||
});
|
||||
state = {
|
||||
fileInfos: new Map(),
|
||||
fileInfos,
|
||||
compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {},
|
||||
latestChangedDtsFile,
|
||||
outSignature: program.outSignature,
|
||||
programEmitPending: program.pendingEmit === undefined ? undefined : toProgramEmitPending(program.pendingEmit, program.options),
|
||||
bundle: buildInfo.bundle,
|
||||
};
|
||||
}
|
||||
else {
|
||||
filePaths = program.fileNames?.map(toPath);
|
||||
filePathsSetList = program.fileIdsList?.map(fileIds => new Set(fileIds.map(toFilePath)));
|
||||
const fileInfos = new Map<Path, BuilderState.FileInfo>();
|
||||
const emitSignatures = program.options?.composite && !outFile(program.options) ? new Map<Path, string>() : undefined;
|
||||
const emitSignatures = program.options?.composite && !outFile(program.options) ? new Map<Path, EmitSignature>() : undefined;
|
||||
program.fileInfos.forEach((fileInfo, index) => {
|
||||
const path = toFilePath(index + 1 as ProgramBuildInfoFileId);
|
||||
const stateFileInfo = toBuilderStateFileInfo(fileInfo);
|
||||
const stateFileInfo = toBuilderStateFileInfoForMultiEmit(fileInfo);
|
||||
fileInfos.set(path, stateFileInfo);
|
||||
if (emitSignatures && stateFileInfo.signature) emitSignatures.set(path, stateFileInfo.signature);
|
||||
});
|
||||
program.emitSignatures?.forEach(value => {
|
||||
if (isNumber(value)) emitSignatures!.delete(toFilePath(value));
|
||||
else emitSignatures!.set(toFilePath(value[0]), value[1]);
|
||||
else {
|
||||
const key = toFilePath(value[0]);
|
||||
emitSignatures!.set(key, !isString(value[1]) && !value[1].length ?
|
||||
// File signature is emit signature but differs in map
|
||||
[emitSignatures!.get(key)! as string] :
|
||||
value[1]
|
||||
);
|
||||
}
|
||||
});
|
||||
const fullEmitForOptions = program.affectedFilesPendingEmit ? getBuilderFileEmit(program.options || {}) : undefined;
|
||||
state = {
|
||||
fileInfos,
|
||||
compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {},
|
||||
@@ -1522,9 +1599,7 @@ namespace ts {
|
||||
exportedModulesMap: toManyToManyPathMap(program.exportedModulesMap),
|
||||
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toFilePath(isNumber(value) ? value : value[0]), value => isNumber(value) ? emptyArray : value[1]),
|
||||
hasReusableDiagnostic: true,
|
||||
affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0])),
|
||||
affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0]), toBuilderFileEmit),
|
||||
affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0,
|
||||
affectedFilesPendingEmit: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0]), value => toBuilderFileEmit(value, fullEmitForOptions!)),
|
||||
changedFilesSet: new Set(map(program.changeFileSet, toFilePath)),
|
||||
latestChangedDtsFile,
|
||||
emitSignatures: emitSignatures?.size ? emitSignatures : undefined,
|
||||
@@ -1566,7 +1641,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function toFilePath(fileId: ProgramBuildInfoFileId) {
|
||||
return filePaths![fileId - 1];
|
||||
return filePaths[fileId - 1];
|
||||
}
|
||||
|
||||
function toFilePathsSet(fileIdsListId: ProgramBuildInfoFileIdListId) {
|
||||
@@ -1596,7 +1671,7 @@ namespace ts {
|
||||
const fileInfos = new Map<Path, string>();
|
||||
program.fileInfos.forEach((fileInfo, index) => {
|
||||
const path = toPath(program.fileNames[index], buildInfoDirectory, getCanonicalFileName);
|
||||
const version = isString(fileInfo) ? fileInfo : (fileInfo as ProgramBuildInfoBuilderStateFileInfo).version; // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
const version = isString(fileInfo) ? fileInfo : fileInfo.version;
|
||||
fileInfos.set(path, version);
|
||||
});
|
||||
return fileInfos;
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace ts {
|
||||
name: string;
|
||||
writeByteOrderMark: boolean;
|
||||
text: string;
|
||||
/* @internal */ buildInfo?: BuildInfo
|
||||
/* @internal */ data?: WriteFileCallbackData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,12 +300,65 @@ namespace ts {
|
||||
transpileOptionValue: undefined,
|
||||
defaultValueDescription: Diagnostics.false_unless_composite_is_set
|
||||
},
|
||||
{
|
||||
name: "declaration",
|
||||
shortName: "d",
|
||||
type: "boolean",
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
transpileOptionValue: undefined,
|
||||
description: Diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project,
|
||||
defaultValueDescription: Diagnostics.false_unless_composite_is_set,
|
||||
},
|
||||
{
|
||||
name: "declarationMap",
|
||||
type: "boolean",
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
transpileOptionValue: undefined,
|
||||
defaultValueDescription: false,
|
||||
description: Diagnostics.Create_sourcemaps_for_d_ts_files
|
||||
},
|
||||
{
|
||||
name: "emitDeclarationOnly",
|
||||
type: "boolean",
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Only_output_d_ts_files_and_not_JavaScript_files,
|
||||
transpileOptionValue: undefined,
|
||||
defaultValueDescription: false,
|
||||
},
|
||||
{
|
||||
name: "sourceMap",
|
||||
type: "boolean",
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
defaultValueDescription: false,
|
||||
description: Diagnostics.Create_source_map_files_for_emitted_JavaScript_files,
|
||||
},
|
||||
{
|
||||
name: "inlineSourceMap",
|
||||
type: "boolean",
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript,
|
||||
defaultValueDescription: false,
|
||||
},
|
||||
{
|
||||
name: "assumeChangesOnlyAffectDirectDependencies",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Watch_and_Build_Modes,
|
||||
description: Diagnostics.Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it,
|
||||
defaultValueDescription: false,
|
||||
@@ -341,7 +394,7 @@ namespace ts {
|
||||
affectsSourceFile: true,
|
||||
affectsModuleResolution: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
paramType: Diagnostics.VERSION,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
@@ -369,7 +422,7 @@ namespace ts {
|
||||
})),
|
||||
affectsModuleResolution: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Modules,
|
||||
@@ -480,7 +533,7 @@ namespace ts {
|
||||
type: jsxOptionMap,
|
||||
affectsSourceFile: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsModuleResolution: true,
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
@@ -488,58 +541,12 @@ namespace ts {
|
||||
description: Diagnostics.Specify_what_JSX_code_is_generated,
|
||||
defaultValueDescription: undefined,
|
||||
},
|
||||
{
|
||||
name: "declaration",
|
||||
shortName: "d",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
transpileOptionValue: undefined,
|
||||
description: Diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project,
|
||||
defaultValueDescription: Diagnostics.false_unless_composite_is_set,
|
||||
},
|
||||
{
|
||||
name: "declarationMap",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
transpileOptionValue: undefined,
|
||||
defaultValueDescription: false,
|
||||
description: Diagnostics.Create_sourcemaps_for_d_ts_files
|
||||
},
|
||||
{
|
||||
name: "emitDeclarationOnly",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Only_output_d_ts_files_and_not_JavaScript_files,
|
||||
transpileOptionValue: undefined,
|
||||
defaultValueDescription: false,
|
||||
},
|
||||
{
|
||||
name: "sourceMap",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
defaultValueDescription: false,
|
||||
description: Diagnostics.Create_source_map_files_for_emitted_JavaScript_files,
|
||||
},
|
||||
{
|
||||
name: "outFile",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsDeclarationPath: true,
|
||||
affectsBundleEmitBuildInfo: true,
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.FILE,
|
||||
showInSimplifiedHelpView: true,
|
||||
@@ -551,7 +558,7 @@ namespace ts {
|
||||
name: "outDir",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsDeclarationPath: true,
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.DIRECTORY,
|
||||
@@ -563,7 +570,7 @@ namespace ts {
|
||||
name: "rootDir",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsDeclarationPath: true,
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.LOCATION,
|
||||
@@ -574,9 +581,8 @@ namespace ts {
|
||||
{
|
||||
name: "composite",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBundleEmitBuildInfo: true,
|
||||
// Not setting affectsEmit because we calculate this flag might not affect full emit
|
||||
affectsBuildInfo: true,
|
||||
isTSConfigOnly: true,
|
||||
category: Diagnostics.Projects,
|
||||
transpileOptionValue: undefined,
|
||||
@@ -587,8 +593,7 @@ namespace ts {
|
||||
name: "tsBuildInfoFile",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBundleEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.FILE,
|
||||
category: Diagnostics.Projects,
|
||||
@@ -600,7 +605,7 @@ namespace ts {
|
||||
name: "removeComments",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Emit,
|
||||
defaultValueDescription: false,
|
||||
@@ -619,7 +624,7 @@ namespace ts {
|
||||
name: "importHelpers",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file,
|
||||
defaultValueDescription: false,
|
||||
@@ -633,7 +638,7 @@ namespace ts {
|
||||
})),
|
||||
affectsEmit: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types,
|
||||
defaultValueDescription: ImportsNotUsedAsValues.Remove,
|
||||
@@ -642,7 +647,7 @@ namespace ts {
|
||||
name: "downlevelIteration",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Emit_more_compliant_but_verbose_and_less_performant_JavaScript_for_iteration,
|
||||
defaultValueDescription: false,
|
||||
@@ -664,7 +669,7 @@ namespace ts {
|
||||
// The value of each strictFlag depends on own strictFlag value or this and never accessed directly.
|
||||
// But we need to store `strict` in builf info, even though it won't be examined directly, so that the
|
||||
// flags it controls (e.g. `strictNullChecks`) will be retrieved correctly
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_all_strict_type_checking_options,
|
||||
@@ -674,7 +679,7 @@ namespace ts {
|
||||
name: "noImplicitAny",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_error_reporting_for_expressions_and_declarations_with_an_implied_any_type,
|
||||
@@ -684,7 +689,7 @@ namespace ts {
|
||||
name: "strictNullChecks",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.When_type_checking_take_into_account_null_and_undefined,
|
||||
@@ -694,7 +699,7 @@ namespace ts {
|
||||
name: "strictFunctionTypes",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible,
|
||||
@@ -704,7 +709,7 @@ namespace ts {
|
||||
name: "strictBindCallApply",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Check_that_the_arguments_for_bind_call_and_apply_methods_match_the_original_function,
|
||||
@@ -714,7 +719,7 @@ namespace ts {
|
||||
name: "strictPropertyInitialization",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor,
|
||||
@@ -724,7 +729,7 @@ namespace ts {
|
||||
name: "noImplicitThis",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_error_reporting_when_this_is_given_the_type_any,
|
||||
@@ -734,7 +739,7 @@ namespace ts {
|
||||
name: "useUnknownInCatchVariables",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Default_catch_clause_variables_as_unknown_instead_of_any,
|
||||
@@ -745,7 +750,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsSourceFile: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
strictFlag: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Ensure_use_strict_is_always_emitted,
|
||||
@@ -757,7 +762,7 @@ namespace ts {
|
||||
name: "noUnusedLocals",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_error_reporting_when_local_variables_aren_t_read,
|
||||
defaultValueDescription: false,
|
||||
@@ -766,7 +771,7 @@ namespace ts {
|
||||
name: "noUnusedParameters",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Raise_an_error_when_a_function_parameter_isn_t_read,
|
||||
defaultValueDescription: false,
|
||||
@@ -775,7 +780,7 @@ namespace ts {
|
||||
name: "exactOptionalPropertyTypes",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Interpret_optional_property_types_as_written_rather_than_adding_undefined,
|
||||
defaultValueDescription: false,
|
||||
@@ -784,7 +789,7 @@ namespace ts {
|
||||
name: "noImplicitReturns",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_error_reporting_for_codepaths_that_do_not_explicitly_return_in_a_function,
|
||||
defaultValueDescription: false,
|
||||
@@ -794,7 +799,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enable_error_reporting_for_fallthrough_cases_in_switch_statements,
|
||||
defaultValueDescription: false,
|
||||
@@ -803,7 +808,7 @@ namespace ts {
|
||||
name: "noUncheckedIndexedAccess",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Add_undefined_to_a_type_when_accessed_using_an_index,
|
||||
defaultValueDescription: false,
|
||||
@@ -812,7 +817,7 @@ namespace ts {
|
||||
name: "noImplicitOverride",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Ensure_overriding_members_in_derived_classes_are_marked_with_an_override_modifier,
|
||||
defaultValueDescription: false,
|
||||
@@ -821,7 +826,7 @@ namespace ts {
|
||||
name: "noPropertyAccessFromIndexSignature",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: false,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type,
|
||||
@@ -908,7 +913,7 @@ namespace ts {
|
||||
name: "allowSyntheticDefaultImports",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Interop_Constraints,
|
||||
description: Diagnostics.Allow_import_x_from_y_when_a_module_doesn_t_have_a_default_export,
|
||||
defaultValueDescription: Diagnostics.module_system_or_esModuleInterop
|
||||
@@ -918,7 +923,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Interop_Constraints,
|
||||
description: Diagnostics.Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility,
|
||||
@@ -935,7 +940,7 @@ namespace ts {
|
||||
name: "allowUmdGlobalAccess",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Modules,
|
||||
description: Diagnostics.Allow_accessing_UMD_globals_from_modules,
|
||||
defaultValueDescription: false,
|
||||
@@ -958,7 +963,7 @@ namespace ts {
|
||||
name: "sourceRoot",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
paramType: Diagnostics.LOCATION,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Specify_the_root_path_for_debuggers_to_find_the_reference_source_code,
|
||||
@@ -967,25 +972,16 @@ namespace ts {
|
||||
name: "mapRoot",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
paramType: Diagnostics.LOCATION,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
|
||||
},
|
||||
{
|
||||
name: "inlineSourceMap",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript,
|
||||
defaultValueDescription: false,
|
||||
},
|
||||
{
|
||||
name: "inlineSources",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Include_source_code_in_the_sourcemaps_inside_the_emitted_JavaScript,
|
||||
defaultValueDescription: false,
|
||||
@@ -996,7 +992,7 @@ namespace ts {
|
||||
name: "experimentalDecorators",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
description: Diagnostics.Enable_experimental_support_for_TC39_stage_2_draft_decorators,
|
||||
defaultValueDescription: false,
|
||||
@@ -1006,7 +1002,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
description: Diagnostics.Emit_design_type_metadata_for_decorated_declarations_in_source_files,
|
||||
defaultValueDescription: false,
|
||||
@@ -1032,7 +1028,7 @@ namespace ts {
|
||||
type: "string",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsModuleResolution: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk,
|
||||
@@ -1051,9 +1047,8 @@ namespace ts {
|
||||
name: "out",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsDeclarationPath: true,
|
||||
affectsBundleEmitBuildInfo: true,
|
||||
isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files
|
||||
// for correct behaviour, please use outFile
|
||||
category: Diagnostics.Backwards_Compatibility,
|
||||
@@ -1065,7 +1060,7 @@ namespace ts {
|
||||
name: "reactNamespace",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
description: Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit,
|
||||
defaultValueDescription: "`React`",
|
||||
@@ -1074,7 +1069,7 @@ namespace ts {
|
||||
name: "skipDefaultLibCheck",
|
||||
type: "boolean",
|
||||
// We need to store these to determine whether `lib` files need to be rechecked
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Completeness,
|
||||
description: Diagnostics.Skip_type_checking_d_ts_files_that_are_included_with_TypeScript,
|
||||
defaultValueDescription: false,
|
||||
@@ -1090,7 +1085,7 @@ namespace ts {
|
||||
name: "emitBOM",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Emit_a_UTF_8_Byte_Order_Mark_BOM_in_the_beginning_of_output_files,
|
||||
defaultValueDescription: false,
|
||||
@@ -1102,7 +1097,7 @@ namespace ts {
|
||||
lf: NewLineKind.LineFeed
|
||||
})),
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
paramType: Diagnostics.NEWLINE,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Set_the_newline_character_for_emitting_files,
|
||||
@@ -1112,7 +1107,7 @@ namespace ts {
|
||||
name: "noErrorTruncation",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Output_Formatting,
|
||||
description: Diagnostics.Disable_truncating_types_in_error_messages,
|
||||
defaultValueDescription: false,
|
||||
@@ -1143,7 +1138,7 @@ namespace ts {
|
||||
name: "stripInternal",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Disable_emitting_declarations_that_have_internal_in_their_JSDoc_comments,
|
||||
defaultValueDescription: false,
|
||||
@@ -1184,7 +1179,7 @@ namespace ts {
|
||||
name: "noImplicitUseStrict",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Backwards_Compatibility,
|
||||
description: Diagnostics.Disable_adding_use_strict_directives_in_emitted_JavaScript_files,
|
||||
defaultValueDescription: false,
|
||||
@@ -1193,7 +1188,7 @@ namespace ts {
|
||||
name: "noEmitHelpers",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Disable_generating_custom_helper_functions_like_extends_in_compiled_output,
|
||||
defaultValueDescription: false,
|
||||
@@ -1202,7 +1197,7 @@ namespace ts {
|
||||
name: "noEmitOnError",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
transpileOptionValue: undefined,
|
||||
description: Diagnostics.Disable_emitting_files_if_any_type_checking_errors_are_reported,
|
||||
@@ -1212,7 +1207,7 @@ namespace ts {
|
||||
name: "preserveConstEnums",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Disable_erasing_const_enum_declarations_in_generated_code,
|
||||
defaultValueDescription: false,
|
||||
@@ -1221,7 +1216,7 @@ namespace ts {
|
||||
name: "declarationDir",
|
||||
type: "string",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
affectsDeclarationPath: true,
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.DIRECTORY,
|
||||
@@ -1233,7 +1228,7 @@ namespace ts {
|
||||
name: "skipLibCheck",
|
||||
type: "boolean",
|
||||
// We need to store these to determine whether `lib` files need to be rechecked
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Completeness,
|
||||
description: Diagnostics.Skip_type_checking_all_d_ts_files,
|
||||
defaultValueDescription: false,
|
||||
@@ -1243,7 +1238,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Disable_error_reporting_for_unused_labels,
|
||||
defaultValueDescription: undefined,
|
||||
@@ -1253,7 +1248,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsBindDiagnostics: true,
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Type_Checking,
|
||||
description: Diagnostics.Disable_error_reporting_for_unreachable_code,
|
||||
defaultValueDescription: undefined,
|
||||
@@ -1262,7 +1257,7 @@ namespace ts {
|
||||
name: "suppressExcessPropertyErrors",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Backwards_Compatibility,
|
||||
description: Diagnostics.Disable_reporting_of_excess_property_errors_during_the_creation_of_object_literals,
|
||||
defaultValueDescription: false,
|
||||
@@ -1271,7 +1266,7 @@ namespace ts {
|
||||
name: "suppressImplicitAnyIndexErrors",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Backwards_Compatibility,
|
||||
description: Diagnostics.Suppress_noImplicitAny_errors_when_indexing_objects_that_lack_index_signatures,
|
||||
defaultValueDescription: false,
|
||||
@@ -1296,7 +1291,7 @@ namespace ts {
|
||||
name: "noStrictGenericChecks",
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Backwards_Compatibility,
|
||||
description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types,
|
||||
defaultValueDescription: false,
|
||||
@@ -1306,7 +1301,7 @@ namespace ts {
|
||||
type: "boolean",
|
||||
affectsSemanticDiagnostics: true,
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Language_and_Environment,
|
||||
description: Diagnostics.Emit_ECMAScript_standard_compliant_class_fields,
|
||||
defaultValueDescription: Diagnostics.true_for_ES2022_and_above_including_ESNext
|
||||
@@ -1315,7 +1310,7 @@ namespace ts {
|
||||
name: "preserveValueImports",
|
||||
type: "boolean",
|
||||
affectsEmit: true,
|
||||
affectsMultiFileEmitBuildInfo: true,
|
||||
affectsBuildInfo: true,
|
||||
category: Diagnostics.Emit,
|
||||
description: Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed,
|
||||
defaultValueDescription: false,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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));
|
||||
@@ -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;
|
||||
@@ -331,7 +331,7 @@ namespace ts {
|
||||
tracing?.pop();
|
||||
|
||||
if (!emitSkipped && emittedFilesList) {
|
||||
if (!emitOnlyDtsFiles) {
|
||||
if (!emitOnly) {
|
||||
if (jsFilePath) {
|
||||
emittedFilesList.push(jsFilePath);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -2091,8 +2091,8 @@ namespace ts {
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile,
|
||||
getTransformers(options, customTransformers, emitOnlyDtsFiles),
|
||||
emitOnlyDtsFiles,
|
||||
getTransformers(options, customTransformers, emitOnly),
|
||||
emitOnly,
|
||||
/*onlyBuildInfo*/ false,
|
||||
forceDtsEmit
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace ts {
|
||||
OutOfDateWithSelf,
|
||||
OutOfDateWithUpstream,
|
||||
OutOfDateBuildInfo,
|
||||
OutOfDateOptions,
|
||||
UpstreamOutOfDate,
|
||||
UpstreamBlocked,
|
||||
ComputingUpstream,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace ts {
|
||||
/*@internal*/ pretty?: boolean;
|
||||
incremental?: boolean;
|
||||
assumeChangesOnlyAffectDirectDependencies?: boolean;
|
||||
declaration?: boolean;
|
||||
declarationMap?: boolean;
|
||||
emitDeclarationOnly?: boolean;
|
||||
sourceMap?: boolean;
|
||||
inlineSourceMap?: boolean;
|
||||
|
||||
traceResolution?: boolean;
|
||||
/* @internal */ diagnostics?: boolean;
|
||||
@@ -964,7 +969,7 @@ namespace ts {
|
||||
reportDeclarationDiagnostics,
|
||||
/*write*/ undefined,
|
||||
/*reportSummary*/ undefined,
|
||||
(name, text, writeByteOrderMark, _onError, _sourceFiles, data) => outputFiles.push({ name, text, writeByteOrderMark, buildInfo: data?.buildInfo }),
|
||||
(name, text, writeByteOrderMark, _onError, _sourceFiles, data) => outputFiles.push({ name, text, writeByteOrderMark, data }),
|
||||
cancellationToken,
|
||||
/*emitOnlyDts*/ false,
|
||||
customTransformers || state.host.getCustomTransformers?.(project)
|
||||
@@ -996,12 +1001,15 @@ namespace ts {
|
||||
const isIncremental = isIncrementalCompilation(options);
|
||||
let outputTimeStampMap: ESMap<Path, Date> | undefined;
|
||||
let now: Date | undefined;
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark, buildInfo }) => {
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark, data }) => {
|
||||
const path = toPath(state, name);
|
||||
emittedOutputs.set(toPath(state, name), name);
|
||||
if (buildInfo) setBuildInfo(state, buildInfo, projectPath, options, resultFlags);
|
||||
if (data?.buildInfo) setBuildInfo(state, data.buildInfo, projectPath, options, resultFlags);
|
||||
const modifiedTime = data?.differsOnlyInMap ? ts.getModifiedTime(state.host, name) : undefined;
|
||||
writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
if (!isIncremental && state.watch) {
|
||||
// Revert the timestamp for the d.ts that is same
|
||||
if (data?.differsOnlyInMap) state.host.setModifiedTime(name, modifiedTime!);
|
||||
else if (!isIncremental && state.watch) {
|
||||
(outputTimeStampMap ||= getOutputTimeStampMap(state, projectPath)!).set(path, now ||= getCurrentTime(state.host));
|
||||
}
|
||||
});
|
||||
@@ -1119,13 +1127,13 @@ namespace ts {
|
||||
const emittedOutputs = new Map<Path, string>();
|
||||
let resultFlags = BuildResultFlags.DeclarationOutputUnchanged;
|
||||
const existingBuildInfo = state.buildInfoCache.get(projectPath)!.buildInfo || undefined;
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark, buildInfo }) => {
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark, data }) => {
|
||||
emittedOutputs.set(toPath(state, name), name);
|
||||
if (buildInfo) {
|
||||
if ((buildInfo.program as ProgramBundleEmitBuildInfo)?.outSignature !== (existingBuildInfo?.program as ProgramBundleEmitBuildInfo)?.outSignature) {
|
||||
if (data?.buildInfo) {
|
||||
if ((data.buildInfo.program as ProgramBundleEmitBuildInfo)?.outSignature !== (existingBuildInfo?.program as ProgramBundleEmitBuildInfo)?.outSignature) {
|
||||
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
|
||||
}
|
||||
setBuildInfo(state, buildInfo, projectPath, config.options, resultFlags);
|
||||
setBuildInfo(state, data.buildInfo, projectPath, config.options, resultFlags);
|
||||
}
|
||||
writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
});
|
||||
@@ -1626,6 +1634,13 @@ namespace ts {
|
||||
buildInfoFile: buildInfoPath
|
||||
};
|
||||
}
|
||||
|
||||
if (!project.options.noEmit && getPendingEmitKind(project.options, buildInfo.program.options || {})) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateOptions,
|
||||
buildInfoFile: buildInfoPath
|
||||
};
|
||||
}
|
||||
buildInfoProgram = buildInfo.program;
|
||||
}
|
||||
|
||||
@@ -1657,7 +1672,7 @@ namespace ts {
|
||||
if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host);
|
||||
version = buildInfoVersionMap.get(toPath(state, inputFile));
|
||||
const text = version ? state.readFileWithCache(inputFile) : undefined;
|
||||
currentVersion = text && (host.createHash || generateDjb2Hash)(text);
|
||||
currentVersion = text && getSourceFileVersionAsHashFromText(host, text);
|
||||
if (version && version === currentVersion) pseudoInputUpToDate = true;
|
||||
}
|
||||
|
||||
@@ -2394,6 +2409,13 @@ namespace ts {
|
||||
relName(state, configFileName),
|
||||
relName(state, status.buildInfoFile)
|
||||
);
|
||||
case UpToDateStatusType.OutOfDateOptions:
|
||||
return reportStatus(
|
||||
state,
|
||||
Diagnostics.Project_0_is_out_of_date_because_buildinfo_file_1_indicates_there_is_change_in_compilerOptions,
|
||||
relName(state, configFileName),
|
||||
relName(state, status.buildInfoFile)
|
||||
);
|
||||
case UpToDateStatusType.UpToDate:
|
||||
if (status.newestInputFileTime !== undefined) {
|
||||
return reportStatus(
|
||||
|
||||
@@ -4261,6 +4261,7 @@ namespace ts {
|
||||
/*@internal*/ sourceMapUrlPos?: number;
|
||||
/*@internal*/ buildInfo?: BuildInfo;
|
||||
/*@internal*/ diagnostics?: readonly DiagnosticWithLocation[];
|
||||
/*@internal*/ differsOnlyInMap?: true;
|
||||
}
|
||||
export type WriteFileCallback = (
|
||||
fileName: string,
|
||||
@@ -4369,6 +4370,11 @@ namespace ts {
|
||||
/*@internal*/
|
||||
export type FilePreprocessingDiagnostics = FilePreprocessingReferencedDiagnostic | FilePreprocessingFileExplainingDiagnostic;
|
||||
|
||||
/*@internal*/
|
||||
export const enum EmitOnly{
|
||||
Js,
|
||||
Dts,
|
||||
}
|
||||
export interface Program extends ScriptReferenceHost {
|
||||
getCurrentDirectory(): string;
|
||||
/**
|
||||
@@ -4404,7 +4410,7 @@ namespace ts {
|
||||
*/
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
|
||||
/*@internal*/
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult; // eslint-disable-line @typescript-eslint/unified-signatures
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult; // eslint-disable-line @typescript-eslint/unified-signatures
|
||||
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
@@ -4468,7 +4474,7 @@ namespace ts {
|
||||
/*@internal*/ forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined;
|
||||
/*@internal*/ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined;
|
||||
/*@internal*/ isSourceOfProjectReferenceRedirect(fileName: string): boolean;
|
||||
/*@internal*/ getProgramBuildInfo?(): ProgramBuildInfo | undefined;
|
||||
/*@internal*/ getBuildInfo?(bundle: BundleBuildInfo | undefined): BuildInfo;
|
||||
/*@internal*/ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
|
||||
/**
|
||||
* This implementation handles file exists to be true if file is source of project reference redirect when program is created using useSourceOfProjectReferenceRedirect
|
||||
@@ -6856,8 +6862,7 @@ namespace ts {
|
||||
affectsEmit?: true; // true if the options affects emit
|
||||
affectsProgramStructure?: true; // true if program should be reconstructed from root files if option changes and does not affect module resolution as affectsModuleResolution indirectly means program needs to reconstructed
|
||||
affectsDeclarationPath?: true; // true if the options affects declaration file path computed
|
||||
affectsMultiFileEmitBuildInfo?: true; // true if this options should be emitted in buildInfo without --out
|
||||
affectsBundleEmitBuildInfo?: true; // true if this options should be emitted in buildInfo with --out
|
||||
affectsBuildInfo?: true; // true if this options should be emitted in buildInfo
|
||||
transpileOptionValue?: boolean | undefined; // If set this means that the option should be set to this value when transpiling
|
||||
extraValidation?: (value: CompilerOptionsValue) => [DiagnosticMessage, ...string[]] | undefined; // Additional validation to be performed for the value to be valid
|
||||
}
|
||||
@@ -7534,7 +7539,7 @@ namespace ts {
|
||||
getPrependNodes(): readonly (InputFiles | UnparsedSource)[];
|
||||
|
||||
writeFile: WriteFileCallback;
|
||||
getProgramBuildInfo(): ProgramBuildInfo | undefined;
|
||||
getBuildInfo(bundle: BundleBuildInfo | undefined): BuildInfo | undefined;
|
||||
getSourceFileFromReference: Program["getSourceFileFromReference"];
|
||||
readonly redirectTargetsMap: RedirectTargetsMap;
|
||||
createHash?(data: string): string;
|
||||
|
||||
@@ -626,13 +626,50 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function getSourceFileVersionAsHashFromText(host: Pick<CompilerHost, "createHash">, text: string) {
|
||||
// If text can contain the sourceMapUrl ignore sourceMapUrl for calcualting hash
|
||||
if (text.match(sourceMapCommentRegExpDontCareLineStart)) {
|
||||
let lineEnd = text.length;
|
||||
let lineStart = lineEnd;
|
||||
for (let pos = lineEnd - 1; pos >= 0; pos--) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
switch (ch) {
|
||||
case CharacterCodes.lineFeed:
|
||||
if (pos && text.charCodeAt(pos - 1) === CharacterCodes.carriageReturn) {
|
||||
pos--;
|
||||
}
|
||||
// falls through
|
||||
case CharacterCodes.carriageReturn:
|
||||
break;
|
||||
default:
|
||||
if (ch < CharacterCodes.maxAsciiCharacter || !isLineBreak(ch)) {
|
||||
lineStart = pos;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// This is start of the line
|
||||
const line = text.substring(lineStart, lineEnd);
|
||||
if (line.match(sourceMapCommentRegExp)) {
|
||||
text = text.substring(0, lineStart);
|
||||
break;
|
||||
}
|
||||
// If we see a non-whitespace/map comment-like line, break, to avoid scanning up the entire file
|
||||
else if (!line.match(whitespaceOrMapCommentRegExp)){
|
||||
break;
|
||||
}
|
||||
lineEnd = lineStart;
|
||||
}
|
||||
}
|
||||
return (host.createHash || generateDjb2Hash)(text);
|
||||
}
|
||||
|
||||
export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost, host: { createHash?(data: string): string; }) {
|
||||
const originalGetSourceFile = compilerHost.getSourceFile;
|
||||
const computeHash = maybeBind(host, host.createHash) || generateDjb2Hash;
|
||||
compilerHost.getSourceFile = (...args) => {
|
||||
const result = originalGetSourceFile.call(compilerHost, ...args);
|
||||
if (result) {
|
||||
result.version = computeHash(result.text);
|
||||
result.version = getSourceFileVersionAsHashFromText(host, result.text);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ts {
|
||||
buildInfo = getBuildInfo(buildInfoPath, content);
|
||||
}
|
||||
if (!buildInfo || buildInfo.version !== version || !buildInfo.program) return undefined;
|
||||
return createBuilderProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host);
|
||||
return createBuilderProgramUsingProgramBuildInfo(buildInfo, buildInfoPath, host);
|
||||
}
|
||||
|
||||
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
"unittests/services/transpile.ts",
|
||||
"unittests/tsbuild/amdModulesWithOut.ts",
|
||||
"unittests/tsbuild/clean.ts",
|
||||
"unittests/tsbuild/commandLine.ts",
|
||||
"unittests/tsbuild/configFileErrors.ts",
|
||||
"unittests/tsbuild/configFileExtends.ts",
|
||||
"unittests/tsbuild/containerOnlyReferenced.ts",
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace ts {
|
||||
assertParseResult("parse build with --incremental", ["--incremental", "tests"]);
|
||||
assertParseResult("parse build with --locale en-us", ["--locale", "en-us", "src"]);
|
||||
assertParseResult("parse build with --tsBuildInfoFile", ["--tsBuildInfoFile", "build.tsbuildinfo", "tests"]);
|
||||
assertParseResult("reports other common may not be used with --build flags", ["--declaration", "--strict"]);
|
||||
assertParseResult("reports other common may not be used with --build flags", ["--strict"]);
|
||||
|
||||
describe("Combining options that make no sense together", () => {
|
||||
function verifyInvalidCombination(flag1: keyof BuildOptions, flag2: keyof BuildOptions) {
|
||||
|
||||
427
src/testRunner/unittests/tsbuild/commandLine.ts
Normal file
427
src/testRunner/unittests/tsbuild/commandLine.ts
Normal file
@@ -0,0 +1,427 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
describe("different options::", () => {
|
||||
function withOptionChange(subScenario: string, ...options: readonly string[]): TestTscEdit {
|
||||
return {
|
||||
subScenario,
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose", ...options]
|
||||
};
|
||||
}
|
||||
function noChangeWithSubscenario(subScenario: string): TestTscEdit {
|
||||
return { ...noChangeRun, subScenario };
|
||||
}
|
||||
function withOptionChangeAndDiscrepancyExplanation(subScenario: string, option: string): TestTscEdit {
|
||||
return {
|
||||
...withOptionChange(subScenario, option),
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/\-/g, "")}`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
|
||||
]
|
||||
};
|
||||
}
|
||||
function withEmitDeclarationOnlyChangeAndDiscrepancyExplanation(subScenario: string): TestTscEdit {
|
||||
const edit = withOptionChangeAndDiscrepancyExplanation(subScenario, "--emitDeclarationOnly");
|
||||
const discrepancyExplanation = edit.discrepancyExplanation!;
|
||||
edit.discrepancyExplanation = () => [
|
||||
...discrepancyExplanation(),
|
||||
`Clean build info does not have js section because its fresh build`,
|
||||
`Incremental build info has js section from old build`
|
||||
];
|
||||
return edit;
|
||||
}
|
||||
function withOptionChangeAndExportExplanation(subScenario: string, ...options: readonly string[]): TestTscEdit {
|
||||
return {
|
||||
...withOptionChange(subScenario, ...options),
|
||||
discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation,
|
||||
};
|
||||
}
|
||||
function nochangeWithIncrementalDeclarationFromBeforeExplaination(): TestTscEdit {
|
||||
return {
|
||||
...noChangeRun,
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo will have compilerOptions {}`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
|
||||
],
|
||||
};
|
||||
}
|
||||
function nochangeWithIncrementalOutDeclarationFromBeforeExplaination(): TestTscEdit {
|
||||
const edit = nochangeWithIncrementalDeclarationFromBeforeExplaination();
|
||||
const discrepancyExplanation = edit.discrepancyExplanation!;
|
||||
edit.discrepancyExplanation = () => [
|
||||
...discrepancyExplanation(),
|
||||
`Clean build does not have dts bundle section`,
|
||||
`Incremental build contains the dts build section from before`,
|
||||
];
|
||||
return edit;
|
||||
}
|
||||
function localChange(): TestTscEdit {
|
||||
return {
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "Local = 1", "Local = 10"),
|
||||
};
|
||||
}
|
||||
function fs(options: CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": JSON.stringify({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/src/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
});
|
||||
}
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "different options",
|
||||
fs: () => fs({ composite: true }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
noChangeRun,
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything", "--emitDeclarationOnly"),
|
||||
noChangeRun,
|
||||
localChange(),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "different options with outFile",
|
||||
fs: () => fs({ composite: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
noChangeRun,
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"),
|
||||
withEmitDeclarationOnlyChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything"),
|
||||
noChangeRun,
|
||||
localChange(),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "different options with incremental",
|
||||
fs: () => fs({ incremental: true }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
edits: [
|
||||
withOptionChangeAndExportExplanation("with sourceMap", "--sourceMap"),
|
||||
withOptionChangeAndExportExplanation("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChange("with declaration, emit Dts and should not emit js", "--declaration"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalDeclarationFromBeforeExplaination(),
|
||||
localChange(),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalDeclarationFromBeforeExplaination(),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("emit js files"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "different options with incremental with outFile",
|
||||
fs: () => fs({ incremental: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChange("with declaration, emit Dts and should not emit js", "--declaration"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalOutDeclarationFromBeforeExplaination(),
|
||||
localChange(),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalOutDeclarationFromBeforeExplaination(),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("emit js files"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
});
|
||||
describe("emitDeclarationOnly::", () => {
|
||||
function fs(options: CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project1/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: compilerOptionsToConfigJson(options),
|
||||
}),
|
||||
"/src/project1/src/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project1/src/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project1/src/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project1/src/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
"/src/project2/src/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: compilerOptionsToConfigJson(options),
|
||||
references: [{ path: "../../project1/src" }],
|
||||
}),
|
||||
"/src/project2/src/e.ts": `export const e = 10;`,
|
||||
"/src/project2/src/f.ts": `import { a } from "${options.outFile ? "a" : "../../project1/src/a"}"; export const f = a;`,
|
||||
"/src/project2/src/g.ts": `import { b } from "${options.outFile ? "b" : "../../project1/src/b"}"; export const g = b;`,
|
||||
});
|
||||
}
|
||||
function verifyWithIncremental(options: CompilerOptions) {
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: subScenario("emitDeclarationOnly on commandline"),
|
||||
fs: () => fs(options),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "export const aaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
...noChangeRun,
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo for both projects will have compilerOptions with composite and emitDeclarationOnly`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info for projects is from before which has option composite only`,
|
||||
]
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const aaaa = 10;"),
|
||||
// --out without composite doesnt emit buildInfo without emitting program so it wouldnt have project2 tsbuildInfo so no mismatch
|
||||
discrepancyExplanation: options.incremental && options.outFile ? undefined : () => [
|
||||
`Clean build tsbuildinfo for project2 will have compilerOptions with composite and emitDeclarationOnly`,
|
||||
`Incremental build will detect that it doesnt need to rebuild project2 so tsbuildinfo for it is from before which has option composite only`,
|
||||
],
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: subScenario("emitDeclarationOnly false on commandline"),
|
||||
fs: () => fs({ ...options, emitDeclarationOnly: true }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
...noChangeRun,
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo for both projects will have compilerOptions with composite and emitDeclarationOnly`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info for projects is from before which has option composite as true but emitDeclrationOnly as false`,
|
||||
]
|
||||
},
|
||||
{
|
||||
subScenario: "no change run with js emit",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
function subScenario(text: string) {
|
||||
return `${text}${options.composite ? "" : " with declaration and incremental"}${options.outFile ? " with outFile" : ""}`;
|
||||
}
|
||||
}
|
||||
verifyWithIncremental({ composite: true });
|
||||
verifyWithIncremental({ incremental: true, declaration: true });
|
||||
verifyWithIncremental({ composite: true, outFile: "../outFile.js", module: ModuleKind.AMD });
|
||||
verifyWithIncremental({ incremental: true, declaration: true, outFile: "../outFile.js", module: ModuleKind.AMD });
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "emitDeclarationOnly on commandline with declaration",
|
||||
fs: () => fs({ declaration: true }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "export const aaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const aaaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "emitDeclarationOnly false on commandline with declaration",
|
||||
fs: () => fs({ declaration: true, emitDeclarationOnly: true }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "no change run with js emit",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "emitDeclarationOnly on commandline with declaration with outFile",
|
||||
fs: () => fs({ declaration: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "export const aaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const aaaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "non local change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change without emitDeclarationOnly",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "commandLine",
|
||||
subScenario: "emitDeclarationOnly false on commandline with declaration with outFile",
|
||||
fs: () => fs({ declaration: true, emitDeclarationOnly: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
subScenario: "emit js files",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "no change run with js emit",
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
subScenario: "js emit with change",
|
||||
modifyFs: fs => appendText(fs, "/src/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -9,13 +9,6 @@ namespace ts {
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in config file", () => {
|
||||
function discrepancyExplanation() {
|
||||
return [
|
||||
"During incremental build, tsbuildinfo is not emitted, so declaration option is not present",
|
||||
"Clean build has declaration option in tsbuildinfo",
|
||||
];
|
||||
}
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "configFileErrors",
|
||||
subScenario: "reports syntax errors in config file",
|
||||
@@ -39,14 +32,16 @@ namespace ts {
|
||||
modifyFs: fs => replaceText(fs, "/src/tsconfig.json", ",", `,
|
||||
"declaration": true,`),
|
||||
subScenario: "reports syntax errors after change to config file",
|
||||
discrepancyExplanation
|
||||
discrepancyExplanation: () => [
|
||||
"During incremental build, tsbuildinfo is not emitted, so declaration option is not present",
|
||||
"Clean build has declaration option in tsbuildinfo",
|
||||
],
|
||||
},
|
||||
{
|
||||
modifyFs: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"),
|
||||
subScenario: "reports syntax errors after change to ts file",
|
||||
discrepancyExplanation,
|
||||
},
|
||||
{ ...noChangeRun, discrepancyExplanation },
|
||||
noChangeRun,
|
||||
{
|
||||
modifyFs: fs => fs.writeFileSync(
|
||||
"/src/tsconfig.json",
|
||||
|
||||
@@ -198,11 +198,12 @@ interface Symbol {
|
||||
}
|
||||
|
||||
type ReadableProgramBuildInfoDiagnostic = string | [string, readonly ReusableDiagnostic[]];
|
||||
type ReadableProgramBuilderInfoFilePendingEmit = [original: string | [string], emitKind: "DtsOnly" | "Full"];
|
||||
type ReadableProgramBuildInfoEmitSignature = string | [string, string];
|
||||
type ReadableProgramBuildInfoFileInfo = Omit<BuilderState.FileInfo, "impliedFormat"> & {
|
||||
type ReadableBuilderFileEmit = string & { __readableBuilderFileEmit: any; };
|
||||
type ReadableProgramBuilderInfoFilePendingEmit = [original: string | [string], emitKind: ReadableBuilderFileEmit];
|
||||
type ReadableProgramBuildInfoEmitSignature = string | [string, EmitSignature | []];
|
||||
type ReadableProgramBuildInfoFileInfo<T> = Omit<BuilderState.FileInfo, "impliedFormat"> & {
|
||||
impliedFormat: string | undefined;
|
||||
original: ProgramBuildInfoBuilderStateFileInfo | undefined;
|
||||
original: T | undefined;
|
||||
};
|
||||
type ReadableProgramMultiFileEmitBuildInfo = Omit<ProgramMultiFileEmitBuildInfo,
|
||||
"fileIdsList" | "fileInfos" |
|
||||
@@ -210,7 +211,7 @@ interface Symbol {
|
||||
"affectedFilesPendingEmit" | "changeFileSet" | "emitSignatures"
|
||||
> & {
|
||||
fileNamesList: readonly (readonly string[])[] | undefined;
|
||||
fileInfos: MapLike<ReadableProgramBuildInfoFileInfo>;
|
||||
fileInfos: MapLike<ReadableProgramBuildInfoFileInfo<ProgramMultiFileEmitBuildInfoFileInfo>>;
|
||||
referencedMap: MapLike<string[]> | undefined;
|
||||
exportedModulesMap: MapLike<string[]> | undefined;
|
||||
semanticDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined;
|
||||
@@ -218,8 +219,10 @@ interface Symbol {
|
||||
changeFileSet: readonly string[] | undefined;
|
||||
emitSignatures: readonly ReadableProgramBuildInfoEmitSignature[] | undefined;
|
||||
};
|
||||
type ReadableProgramBundleEmitBuildInfo = Omit<ProgramBundleEmitBuildInfo, "fileInfos"> & {
|
||||
fileInfos: MapLike<string>;
|
||||
type ReadableProgramBuildInfoBundlePendingEmit = [emitKind: ReadableBuilderFileEmit, original: ProgramBuildInfoBundlePendingEmit];
|
||||
type ReadableProgramBundleEmitBuildInfo = Omit<ProgramBundleEmitBuildInfo, "fileInfos" | "pendingEmit"> & {
|
||||
fileInfos: MapLike<string | ReadableProgramBuildInfoFileInfo<BuilderState.FileInfo>>;
|
||||
pendingEmit: ReadableProgramBuildInfoBundlePendingEmit | undefined;
|
||||
};
|
||||
|
||||
type ReadableProgramBuildInfo = ReadableProgramMultiFileEmitBuildInfo | ReadableProgramBundleEmitBuildInfo;
|
||||
@@ -233,16 +236,28 @@ interface Symbol {
|
||||
let fileNamesList: string[][] | undefined;
|
||||
if (buildInfo.program && isProgramBundleEmitBuildInfo(buildInfo.program)) {
|
||||
const fileInfos: ReadableProgramBundleEmitBuildInfo["fileInfos"] = {};
|
||||
buildInfo.program?.fileInfos?.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ProgramBuildInfoFileId)] = fileInfo);
|
||||
buildInfo.program?.fileInfos?.forEach((fileInfo, index) =>
|
||||
fileInfos[toFileName(index + 1 as ProgramBuildInfoFileId)] = isString(fileInfo) ?
|
||||
fileInfo :
|
||||
toReadableFileInfo(fileInfo, identity)
|
||||
);
|
||||
const pendingEmit = buildInfo.program.pendingEmit;
|
||||
program = {
|
||||
...buildInfo.program,
|
||||
fileInfos
|
||||
fileInfos,
|
||||
pendingEmit: pendingEmit === undefined ?
|
||||
undefined :
|
||||
[
|
||||
toReadableBuilderFileEmit(toProgramEmitPending(pendingEmit, buildInfo.program.options)),
|
||||
pendingEmit
|
||||
],
|
||||
};
|
||||
}
|
||||
else if (buildInfo.program) {
|
||||
const fileInfos: ReadableProgramMultiFileEmitBuildInfo["fileInfos"] = {};
|
||||
buildInfo.program?.fileInfos?.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ProgramBuildInfoFileId)] = toReadableFileInfo(fileInfo));
|
||||
buildInfo.program?.fileInfos?.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ProgramBuildInfoFileId)] = toReadableFileInfo(fileInfo, toBuilderStateFileInfoForMultiEmit));
|
||||
fileNamesList = buildInfo.program.fileIdsList?.map(fileIdsListId => fileIdsListId.map(toFileName));
|
||||
const fullEmitForOptions = buildInfo.program.affectedFilesPendingEmit ? getBuilderFileEmit(buildInfo.program.options || {}) : undefined;
|
||||
program = buildInfo.program && {
|
||||
fileNames: buildInfo.program.fileNames,
|
||||
fileNamesList,
|
||||
@@ -255,7 +270,7 @@ interface Symbol {
|
||||
toFileName(d) :
|
||||
[toFileName(d[0]), d[1]]
|
||||
),
|
||||
affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(toReadableProgramBuilderInfoFilePendingEmit),
|
||||
affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(value => toReadableProgramBuilderInfoFilePendingEmit(value, fullEmitForOptions!)),
|
||||
changeFileSet: buildInfo.program.changeFileSet?.map(toFileName),
|
||||
emitSignatures: buildInfo.program.emitSignatures?.map(s =>
|
||||
isNumber(s) ?
|
||||
@@ -298,10 +313,10 @@ interface Symbol {
|
||||
return fileNamesList![fileIdsListId - 1];
|
||||
}
|
||||
|
||||
function toReadableFileInfo(fileInfo: ProgramBuildInfoFileInfo): ReadableProgramBuildInfoFileInfo {
|
||||
const info = toBuilderStateFileInfo(fileInfo);
|
||||
function toReadableFileInfo<T>(original: T, toFileInfo: (fileInfo: T) => BuilderState.FileInfo): ReadableProgramBuildInfoFileInfo<T> {
|
||||
const info = toFileInfo(original);
|
||||
return {
|
||||
original: isString(fileInfo) ? undefined : fileInfo,
|
||||
original: isString(original) ? undefined : original,
|
||||
...info,
|
||||
impliedFormat: info.impliedFormat && getNameOfCompilerOptionValue(info.impliedFormat, moduleOptionDeclaration.type),
|
||||
};
|
||||
@@ -316,15 +331,27 @@ interface Symbol {
|
||||
return result;
|
||||
}
|
||||
|
||||
function toReadableProgramBuilderInfoFilePendingEmit(value: ProgramBuilderInfoFilePendingEmit): ReadableProgramBuilderInfoFilePendingEmit {
|
||||
const emitKind = toBuilderFileEmit(value);
|
||||
function toReadableProgramBuilderInfoFilePendingEmit(value: ProgramBuilderInfoFilePendingEmit, fullEmitForOptions: BuilderFileEmit): ReadableProgramBuilderInfoFilePendingEmit {
|
||||
return [
|
||||
isNumber(value) ? toFileName(value) : [toFileName(value[0])],
|
||||
emitKind === BuilderFileEmit.DtsOnly ? "DtsOnly" :
|
||||
emitKind === BuilderFileEmit.Full ? "Full" :
|
||||
Debug.assertNever(emitKind),
|
||||
toReadableBuilderFileEmit(toBuilderFileEmit(value, fullEmitForOptions)),
|
||||
];
|
||||
}
|
||||
|
||||
function toReadableBuilderFileEmit(emit: BuilderFileEmit | undefined): ReadableBuilderFileEmit {
|
||||
let result = "";
|
||||
if (emit) {
|
||||
if (emit & BuilderFileEmit.Js) addFlags("Js");
|
||||
if (emit & BuilderFileEmit.JsMap) addFlags("JsMap");
|
||||
if (emit & BuilderFileEmit.JsInlineMap) addFlags("JsInlineMap");
|
||||
if (emit & BuilderFileEmit.Dts) addFlags("Dts");
|
||||
if (emit & BuilderFileEmit.DtsMap) addFlags("DtsMap");
|
||||
}
|
||||
return (result || "None") as ReadableBuilderFileEmit;
|
||||
function addFlags(flag: string) {
|
||||
result = result ? `${result} | ${flag}` : flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function toPathWithSystem(sys: System, fileName: string): Path {
|
||||
@@ -538,7 +565,7 @@ interface Symbol {
|
||||
} {
|
||||
if (!text) return { buildInfo: text };
|
||||
const readableBuildInfo = JSON.parse(text) as ReadableBuildInfo;
|
||||
let sanitizedFileInfos: MapLike<ReadableProgramBuildInfoFileInfo | string> | undefined;
|
||||
let sanitizedFileInfos: MapLike<string | Omit<ReadableProgramBuildInfoFileInfo<ProgramMultiFileEmitBuildInfoFileInfo> | ReadableProgramBuildInfoFileInfo<BuilderState.FileInfo>, "signature" | "original"> & { signature: undefined; original: undefined; }> | undefined;
|
||||
if (readableBuildInfo.program?.fileInfos) {
|
||||
sanitizedFileInfos = {};
|
||||
for (const id in readableBuildInfo.program.fileInfos) {
|
||||
|
||||
@@ -154,6 +154,23 @@ namespace ts {
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "when declarationMap changes",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
subScenario: "Disable declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"declarationMap": true,`, `"declarationMap": false,`),
|
||||
},
|
||||
{
|
||||
subScenario: "Enable declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"declarationMap": false,`, `"declarationMap": true,`),
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "indicates that it would skip builds during a dry build",
|
||||
|
||||
@@ -425,7 +425,6 @@ declare global {
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when project has strict true",
|
||||
@@ -580,5 +579,241 @@ console.log(a);`,
|
||||
}
|
||||
verifyModifierChange(/*declaration*/ false);
|
||||
verifyModifierChange(/*declaration*/ true);
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: `when declarationMap changes`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
noEmitOnError: true,
|
||||
declaration: true,
|
||||
composite: true,
|
||||
}
|
||||
}),
|
||||
"/src/project/a.ts": "const x = 10;",
|
||||
"/src/project/b.ts": "const y = 10;"
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
{
|
||||
subScenario: "error and enable declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build does not emit any file so will have emitSignatures with all files since they are not emitted`,
|
||||
`Incremental build has emitSignatures from before, so it will have a.ts with signature since file.version isnt same`,
|
||||
`Incremental build will also have emitSignatureDtsMapDiffers for both files since the emitSignatures were without declarationMap but currentOptions have declrationMap`,
|
||||
]
|
||||
},
|
||||
{
|
||||
subScenario: "fix error declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: `when declarationMap changes with outFile`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": JSON.stringify({
|
||||
compilerOptions: {
|
||||
noEmitOnError: true,
|
||||
declaration: true,
|
||||
composite: true,
|
||||
outFile: "../outFile.js",
|
||||
}
|
||||
}),
|
||||
"/src/project/a.ts": "const x = 10;",
|
||||
"/src/project/b.ts": "const y = 10;"
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
{
|
||||
subScenario: "error and enable declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
},
|
||||
{
|
||||
subScenario: "fix error declarationMap",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
describe("different options::", () => {
|
||||
function withOptionChange(subScenario: string, ...options: readonly string[]): TestTscEdit {
|
||||
return {
|
||||
subScenario,
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--p", "/src/project", ...options],
|
||||
};
|
||||
}
|
||||
function noChangeWithSubscenario(subScenario: string): TestTscEdit {
|
||||
return { ...noChangeRun, subScenario };
|
||||
}
|
||||
function withOptionChangeAndDiscrepancyExplanation(subScenario: string, option: string): TestTscEdit {
|
||||
return {
|
||||
...withOptionChange(subScenario, option),
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo will have compilerOptions with composite and ${option.replace(/\-/g, "")}`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option composite only`,
|
||||
]
|
||||
};
|
||||
}
|
||||
function withEmitDeclarationOnlyChangeAndDiscrepancyExplanation(subScenario: string): TestTscEdit {
|
||||
const edit = withOptionChangeAndDiscrepancyExplanation(subScenario, "--emitDeclarationOnly");
|
||||
const discrepancyExplanation = edit.discrepancyExplanation!;
|
||||
edit.discrepancyExplanation = () => [
|
||||
...discrepancyExplanation(),
|
||||
`Clean build info does not have js section because its fresh build`,
|
||||
`Incremental build info has js section from old build`
|
||||
];
|
||||
return edit;
|
||||
}
|
||||
function withOptionChangeAndExportExplanation(subScenario: string, ...options: readonly string[]): TestTscEdit {
|
||||
return {
|
||||
...withOptionChange(subScenario, ...options),
|
||||
discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation,
|
||||
};
|
||||
}
|
||||
function nochangeWithIncrementalDeclarationFromBeforeExplaination(): TestTscEdit {
|
||||
return {
|
||||
...noChangeRun,
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo will have compilerOptions {}`,
|
||||
`Incremental build will detect that it doesnt need to rebuild so tsbuild info is from before which has option declaration and declarationMap`,
|
||||
],
|
||||
};
|
||||
}
|
||||
function nochangeWithIncrementalOutDeclarationFromBeforeExplaination(): TestTscEdit {
|
||||
const edit = nochangeWithIncrementalDeclarationFromBeforeExplaination();
|
||||
const discrepancyExplanation = edit.discrepancyExplanation!;
|
||||
edit.discrepancyExplanation = () => [
|
||||
...discrepancyExplanation(),
|
||||
`Clean build does not have dts bundle section`,
|
||||
`Incremental build contains the dts build section from before`,
|
||||
];
|
||||
return edit;
|
||||
}
|
||||
function localChange(): TestTscEdit {
|
||||
return {
|
||||
subScenario: "local change",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/a.ts", "Local = 1", "Local = 10"),
|
||||
};
|
||||
}
|
||||
function fs(options: CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": JSON.stringify({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/src/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
});
|
||||
}
|
||||
function enableDeclarationMap(): TestTscEdit {
|
||||
return {
|
||||
subScenario: "declarationMap enabling",
|
||||
modifyFs: fs => {
|
||||
const config = JSON.parse(fs.readFileSync("/src/project/tsconfig.json", "utf-8"));
|
||||
config.compilerOptions.declarationMap = true;
|
||||
fs.writeFileSync("/src/project/tsconfig.json", JSON.stringify(config));
|
||||
},
|
||||
};
|
||||
}
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "different options",
|
||||
fs: () => fs({ composite: true }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
noChangeRun,
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything", "--emitDeclarationOnly"),
|
||||
noChangeRun,
|
||||
localChange(),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
enableDeclarationMap(),
|
||||
withOptionChange("with sourceMap should not emit d.ts", "--sourceMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "different options with outFile",
|
||||
fs: () => fs({ composite: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
noChangeRun,
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
noChangeWithSubscenario("should re-emit only dts so they dont contain sourcemap"),
|
||||
withEmitDeclarationOnlyChangeAndDiscrepancyExplanation("with emitDeclarationOnly should not emit anything"),
|
||||
noChangeRun,
|
||||
localChange(),
|
||||
withOptionChangeAndDiscrepancyExplanation("with declaration should not emit anything", "--declaration"),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
enableDeclarationMap(),
|
||||
withOptionChange("with sourceMap should not emit d.ts", "--sourceMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "different options with incremental",
|
||||
fs: () => fs({ incremental: true }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
withOptionChangeAndExportExplanation("with sourceMap", "--sourceMap"),
|
||||
withOptionChangeAndExportExplanation("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChange("with declaration, emit Dts and should not emit js", "--declaration"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalDeclarationFromBeforeExplaination(),
|
||||
localChange(),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalDeclarationFromBeforeExplaination(),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("emit js files"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "different options with incremental with outFile",
|
||||
fs: () => fs({ incremental: true, outFile: "../outFile.js", module: ModuleKind.AMD }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
withOptionChange("with declaration, emit Dts and should not emit js", "--declaration"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalOutDeclarationFromBeforeExplaination(),
|
||||
localChange(),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
nochangeWithIncrementalOutDeclarationFromBeforeExplaination(),
|
||||
withOptionChange("with inlineSourceMap", "--inlineSourceMap"),
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("emit js files"),
|
||||
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
|
||||
withOptionChange("with declaration and declarationMap, should not re-emit", "--declaration", "--declarationMap"),
|
||||
],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -410,5 +410,36 @@ X;`,
|
||||
],
|
||||
baselineDependencies: true,
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario: "projectsWithReferences",
|
||||
subScenario: "when declarationMap changes for dependency",
|
||||
sys: () => createSystemWithSolutionBuild(
|
||||
["core"],
|
||||
[
|
||||
libFile,
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "core/tsconfig.json"),
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "core/index.ts"),
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "core/anotherModule.ts"),
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "core/some_decl.d.ts"),
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "logic/tsconfig.json"),
|
||||
TestFSWithWatch.getTsBuildProjectFile("sample1", "logic/index.ts"),
|
||||
],
|
||||
{ currentDirectory: `${TestFSWithWatch.tsbuildProjectsLocation}/sample1` }
|
||||
),
|
||||
commandLineArgs: ["-w", "-p", "logic"],
|
||||
changes: [
|
||||
{
|
||||
caption: "change declration map in core",
|
||||
change: sys => {
|
||||
replaceFileText(sys, TestFSWithWatch.getTsBuildProjectFilePath("sample1", "core/tsconfig.json"), `"declarationMap": true,`, `"declarationMap": false,`);
|
||||
const solutionBuilder = createSolutionBuilder(sys, ["core"]);
|
||||
solutionBuilder.build();
|
||||
},
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(0),
|
||||
},
|
||||
],
|
||||
baselineDependencies: true
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -611,4 +611,97 @@ namespace ts.tscWatch {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitOnlyDtsFiles", () => {
|
||||
function verify(subScenario: string, outFile?: string) {
|
||||
it(subScenario, () => {
|
||||
const system = createWatchedSystem({
|
||||
[`${projectRoot}/tsconfig.json`]: JSON.stringify({
|
||||
compilerOptions: { composite: true, noEmitOnError: true, module: "amd", outFile },
|
||||
files: ["a.ts", "b.ts"],
|
||||
}),
|
||||
[`${projectRoot}/a.ts`]: "export const x = 10;",
|
||||
[`${projectRoot}/b.ts`]: "export const y: 10 = 20;",
|
||||
[libFile.path]: libFile.content,
|
||||
}, { currentDirectory: projectRoot });
|
||||
const baseline = createBaseline(system);
|
||||
const compilerHost = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
cb: baseline.cb,
|
||||
system,
|
||||
configFileName: `${projectRoot}/tsconfig.json`,
|
||||
optionsToExtend: { extendedDiagnostics: true }
|
||||
});
|
||||
const originalEmitProgram = compilerHost.afterProgramCreate;
|
||||
compilerHost.afterProgramCreate = myAfterProgramCreate;
|
||||
let callFullEmit = true;
|
||||
const watch = createWatchProgram(compilerHost);
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario,
|
||||
commandLineArgs: ["--w", "--extendedDiagnostics"],
|
||||
...baseline,
|
||||
changes: [
|
||||
{
|
||||
caption: "Fix error but run emit with emitOnlyDts",
|
||||
change: sys => {
|
||||
sys.writeFile(`${projectRoot}/b.ts`, `export const y = 10;`);
|
||||
callFullEmit = false;
|
||||
},
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
},
|
||||
{
|
||||
caption: "Emit with emitOnlyDts shouldnt emit anything",
|
||||
change: () => {
|
||||
const program = watch.getCurrentProgram();
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true);
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.checkTimeoutQueueLength(0),
|
||||
},
|
||||
{
|
||||
caption: "Emit all files",
|
||||
change: () => {
|
||||
const program = watch.getCurrentProgram();
|
||||
program.emit();
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.checkTimeoutQueueLength(0),
|
||||
},
|
||||
{
|
||||
caption: "Emit with emitOnlyDts shouldnt emit anything",
|
||||
change: () => {
|
||||
const program = watch.getCurrentProgram();
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true);
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.checkTimeoutQueueLength(0),
|
||||
},
|
||||
{
|
||||
caption: "Emit full should not emit anything",
|
||||
change: () => {
|
||||
const program = watch.getCurrentProgram();
|
||||
program.emit();
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.checkTimeoutQueueLength(0),
|
||||
},
|
||||
],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
|
||||
function myAfterProgramCreate(program: EmitAndSemanticDiagnosticsBuilderProgram) {
|
||||
if (callFullEmit) {
|
||||
originalEmitProgram!.call(compilerHost, program);
|
||||
}
|
||||
else {
|
||||
program.getSemanticDiagnostics(); // Get Diagnostics
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true);
|
||||
baseline.cb(program);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
verify("when emitting with emitOnlyDtsFiles");
|
||||
verify("when emitting with emitOnlyDtsFiles with outFile", "outFile.js");
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user