mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 10:41:56 -05:00
When emitting all files, emit the changed file first (#18930)
* When emitting all files, emit the changed file first * Export interface
This commit is contained in:
@@ -93,12 +93,14 @@ namespace ts {
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export function createBuilder(
|
||||
getCanonicalFileName: (fileName: string) => string,
|
||||
getEmitOutput: (program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) => EmitOutput | EmitOutputDetailed,
|
||||
computeHash: (data: string) => string,
|
||||
shouldEmitFile: (sourceFile: SourceFile) => boolean
|
||||
): Builder {
|
||||
export interface BuilderOptions {
|
||||
getCanonicalFileName: (fileName: string) => string;
|
||||
getEmitOutput: (program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) => EmitOutput | EmitOutputDetailed;
|
||||
computeHash: (data: string) => string;
|
||||
shouldEmitFile: (sourceFile: SourceFile) => boolean;
|
||||
}
|
||||
|
||||
export function createBuilder(options: BuilderOptions): Builder {
|
||||
let isModuleEmit: boolean | undefined;
|
||||
const fileInfos = createMap<FileInfo>();
|
||||
const semanticDiagnosticsPerFile = createMap<ReadonlyArray<Diagnostic>>();
|
||||
@@ -181,7 +183,7 @@ namespace ts {
|
||||
ensureProgramGraph(program);
|
||||
|
||||
const sourceFile = program.getSourceFile(path);
|
||||
const singleFileResult = sourceFile && shouldEmitFile(sourceFile) ? [sourceFile.fileName] : [];
|
||||
const singleFileResult = sourceFile && options.shouldEmitFile(sourceFile) ? [sourceFile.fileName] : [];
|
||||
const info = fileInfos.get(path);
|
||||
if (!info || !updateShapeSignature(program, sourceFile, info)) {
|
||||
return singleFileResult;
|
||||
@@ -197,7 +199,7 @@ namespace ts {
|
||||
return { outputFiles: [], emitSkipped: true };
|
||||
}
|
||||
|
||||
return getEmitOutput(program, program.getSourceFileByPath(path), /*emitOnlyDtsFiles*/ false, /*isDetailed*/ false);
|
||||
return options.getEmitOutput(program, program.getSourceFileByPath(path), /*emitOnlyDtsFiles*/ false, /*isDetailed*/ false);
|
||||
}
|
||||
|
||||
function enumerateChangedFilesSet(
|
||||
@@ -220,21 +222,21 @@ namespace ts {
|
||||
onChangedFile: (fileName: string, path: Path) => void,
|
||||
onEmitOutput: (emitOutput: EmitOutputDetailed, sourceFile: SourceFile) => void
|
||||
) {
|
||||
const seenFiles = createMap<SourceFile>();
|
||||
const seenFiles = createMap<true>();
|
||||
enumerateChangedFilesSet(program, onChangedFile, (fileName, sourceFile) => {
|
||||
if (!seenFiles.has(fileName)) {
|
||||
seenFiles.set(fileName, sourceFile);
|
||||
seenFiles.set(fileName, true);
|
||||
if (sourceFile) {
|
||||
// Any affected file shouldnt have the cached diagnostics
|
||||
semanticDiagnosticsPerFile.delete(sourceFile.path);
|
||||
|
||||
const emitOutput = getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed;
|
||||
const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed;
|
||||
onEmitOutput(emitOutput, sourceFile);
|
||||
|
||||
// mark all the emitted source files as seen
|
||||
if (emitOutput.emittedSourceFiles) {
|
||||
for (const file of emitOutput.emittedSourceFiles) {
|
||||
seenFiles.set(file.fileName, file);
|
||||
seenFiles.set(file.fileName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,13 +311,13 @@ namespace ts {
|
||||
const prevSignature = info.signature;
|
||||
let latestSignature: string;
|
||||
if (sourceFile.isDeclarationFile) {
|
||||
latestSignature = computeHash(sourceFile.text);
|
||||
latestSignature = options.computeHash(sourceFile.text);
|
||||
info.signature = latestSignature;
|
||||
}
|
||||
else {
|
||||
const emitOutput = getEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true, /*isDetailed*/ false);
|
||||
const emitOutput = options.getEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true, /*isDetailed*/ false);
|
||||
if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) {
|
||||
latestSignature = computeHash(emitOutput.outputFiles[0].text);
|
||||
latestSignature = options.computeHash(emitOutput.outputFiles[0].text);
|
||||
info.signature = latestSignature;
|
||||
}
|
||||
else {
|
||||
@@ -352,7 +354,7 @@ namespace ts {
|
||||
// Handle triple slash references
|
||||
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
|
||||
for (const referencedFile of sourceFile.referencedFiles) {
|
||||
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, options.getCanonicalFileName);
|
||||
addReferencedFile(referencedPath);
|
||||
}
|
||||
}
|
||||
@@ -365,7 +367,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const fileName = resolvedTypeReferenceDirective.resolvedFileName;
|
||||
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
|
||||
const typeFilePath = toPath(fileName, sourceFileDirectory, options.getCanonicalFileName);
|
||||
addReferencedFile(typeFilePath);
|
||||
});
|
||||
}
|
||||
@@ -381,18 +383,26 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the emittable files from the program
|
||||
* Gets all the emittable files from the program.
|
||||
* @param firstSourceFile This one will be emitted first. See https://github.com/Microsoft/TypeScript/issues/16888
|
||||
*/
|
||||
function getAllEmittableFiles(program: Program) {
|
||||
function getAllEmittableFiles(program: Program, firstSourceFile: SourceFile): string[] {
|
||||
const defaultLibraryFileName = getDefaultLibFileName(program.getCompilerOptions());
|
||||
const sourceFiles = program.getSourceFiles();
|
||||
const result: string[] = [];
|
||||
add(firstSourceFile);
|
||||
for (const sourceFile of sourceFiles) {
|
||||
if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && shouldEmitFile(sourceFile)) {
|
||||
result.push(sourceFile.fileName);
|
||||
if (sourceFile !== firstSourceFile) {
|
||||
add(sourceFile);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
function add(sourceFile: SourceFile): void {
|
||||
if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && options.shouldEmitFile(sourceFile)) {
|
||||
result.push(sourceFile.fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNonModuleEmitHandler(): EmitHandler {
|
||||
@@ -404,14 +414,14 @@ namespace ts {
|
||||
getFilesAffectedByUpdatedShape
|
||||
};
|
||||
|
||||
function getFilesAffectedByUpdatedShape(program: Program, _sourceFile: SourceFile, singleFileResult: string[]): string[] {
|
||||
function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] {
|
||||
const options = program.getCompilerOptions();
|
||||
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
|
||||
// so returning the file itself is good enough.
|
||||
if (options && (options.out || options.outFile)) {
|
||||
return singleFileResult;
|
||||
}
|
||||
return getAllEmittableFiles(program);
|
||||
return getAllEmittableFiles(program, sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,11 +494,11 @@ namespace ts {
|
||||
|
||||
function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] {
|
||||
if (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile)) {
|
||||
return getAllEmittableFiles(program);
|
||||
return getAllEmittableFiles(program, sourceFile);
|
||||
}
|
||||
|
||||
const options = program.getCompilerOptions();
|
||||
if (options && (options.isolatedModules || options.out || options.outFile)) {
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) {
|
||||
return singleFileResult;
|
||||
}
|
||||
|
||||
@@ -498,7 +508,7 @@ namespace ts {
|
||||
|
||||
const seenFileNamesMap = createMap<string>();
|
||||
const setSeenFileName = (path: Path, sourceFile: SourceFile) => {
|
||||
seenFileNamesMap.set(path, sourceFile && shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined);
|
||||
seenFileNamesMap.set(path, sourceFile && options.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined);
|
||||
};
|
||||
|
||||
// Start with the paths this file was referenced by
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace ts {
|
||||
getCurrentDirectory()
|
||||
);
|
||||
// There is no extra check needed since we can just rely on the program to decide emit
|
||||
const builder = createBuilder(getCanonicalFileName, getFileEmitOutput, computeHash, _sourceFile => true);
|
||||
const builder = createBuilder({ getCanonicalFileName, getEmitOutput: getFileEmitOutput, computeHash, shouldEmitFile: () => true });
|
||||
|
||||
synchronizeProgram();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user