mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-18 03:43:28 -06:00
Simplifty declaration emitter logic by using forEachExpectedEmitFile
This commit is contained in:
parent
06bf08c17f
commit
2b582a0b71
@ -36,11 +36,12 @@ namespace ts {
|
||||
return declarationDiagnostics.getDiagnostics(targetSourceFile.fileName);
|
||||
|
||||
function getDeclarationDiagnosticsFromFile({ declarationFilePath }, sources: SourceFile[], isBundledEmit: boolean) {
|
||||
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, !isBundledEmit ? targetSourceFile : undefined);
|
||||
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit);
|
||||
}
|
||||
}
|
||||
|
||||
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string, root?: SourceFile): DeclarationEmit {
|
||||
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
|
||||
sourceFiles: SourceFile[], isBundledEmit: boolean): DeclarationEmit {
|
||||
let newLine = host.getNewLine();
|
||||
let compilerOptions = host.getCompilerOptions();
|
||||
|
||||
@ -67,67 +68,48 @@ namespace ts {
|
||||
// and we could be collecting these paths from multiple files into single one with --out option
|
||||
let referencePathsOutput = "";
|
||||
|
||||
if (root) {
|
||||
// Emitting just a single file, so emit references in this file only
|
||||
if (!compilerOptions.noResolve) {
|
||||
let addedGlobalFileReference = false;
|
||||
forEach(root.referencedFiles, fileReference => {
|
||||
let referencedFile = tryResolveScriptReference(host, root, fileReference);
|
||||
// Emit references corresponding to each file
|
||||
let emittedReferencedFiles: SourceFile[] = [];
|
||||
let addedGlobalFileReference = false;
|
||||
forEach(sourceFiles, sourceFile => {
|
||||
if (!isJavaScript(sourceFile.fileName)) {
|
||||
// Check what references need to be added
|
||||
if (!compilerOptions.noResolve) {
|
||||
forEach(sourceFile.referencedFiles, fileReference => {
|
||||
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
|
||||
|
||||
// All the references that are not going to be part of same file
|
||||
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
|
||||
shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
|
||||
!addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
|
||||
|
||||
writeReferencePath(referencedFile);
|
||||
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
|
||||
addedGlobalFileReference = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
emitSourceFile(root);
|
||||
|
||||
// create asynchronous output for the importDeclarations
|
||||
if (moduleElementDeclarationEmitInfo.length) {
|
||||
let oldWriter = writer;
|
||||
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
|
||||
if (aliasEmitInfo.isVisible) {
|
||||
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
|
||||
createAndSetNewTextWriterWithSymbolWriter();
|
||||
Debug.assert(aliasEmitInfo.indent === 0);
|
||||
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
|
||||
aliasEmitInfo.asynchronousOutput = writer.getText();
|
||||
}
|
||||
});
|
||||
setWriter(oldWriter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Emit references corresponding to this file
|
||||
let emittedReferencedFiles: SourceFile[] = [];
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
if (!isExternalModuleOrDeclarationFile(sourceFile) && !isJavaScript(sourceFile.fileName)) {
|
||||
// Check what references need to be added
|
||||
if (!compilerOptions.noResolve) {
|
||||
forEach(sourceFile.referencedFiles, fileReference => {
|
||||
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
|
||||
|
||||
// If the reference file is a declaration file or an external module, emit that reference
|
||||
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
|
||||
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
|
||||
|
||||
writeReferencePath(referencedFile);
|
||||
emittedReferencedFiles.push(referencedFile);
|
||||
// Emit reference in dts, if the file reference was not already emitted
|
||||
if (referencedFile && !contains(emittedReferencedFiles, referencedFile)) {
|
||||
// Add a reference to generated dts file,
|
||||
// global file reference is added only
|
||||
// - if it is not bundled emit (because otherwise it would be self reference)
|
||||
// - and it is not already added
|
||||
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
|
||||
addedGlobalFileReference = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
emitSourceFile(sourceFile);
|
||||
emittedReferencedFiles.push(referencedFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
emitSourceFile(sourceFile);
|
||||
|
||||
// create asynchronous output for the importDeclarations
|
||||
if (moduleElementDeclarationEmitInfo.length) {
|
||||
let oldWriter = writer;
|
||||
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
|
||||
if (aliasEmitInfo.isVisible) {
|
||||
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
|
||||
createAndSetNewTextWriterWithSymbolWriter();
|
||||
Debug.assert(aliasEmitInfo.indent === 0);
|
||||
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
|
||||
aliasEmitInfo.asynchronousOutput = writer.getText();
|
||||
}
|
||||
});
|
||||
setWriter(oldWriter);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
reportedDeclarationError,
|
||||
@ -1592,33 +1574,51 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeReferencePath(referencedFile: SourceFile) {
|
||||
/**
|
||||
* Adds the reference to referenced file, returns true if global file reference was emitted
|
||||
* @param referencedFile
|
||||
* @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not
|
||||
*/
|
||||
function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean): boolean {
|
||||
let declFileName: string;
|
||||
if (referencedFile.flags & NodeFlags.DeclarationFile) {
|
||||
let addedBundledEmitReference = false;
|
||||
if (isDeclarationFile(referencedFile)) {
|
||||
// Declaration file, use declaration file name
|
||||
declFileName = referencedFile.fileName;
|
||||
}
|
||||
else {
|
||||
// declaration file name
|
||||
let { declarationFilePath, jsFilePath } = getEmitFileNames(referencedFile, host);
|
||||
Debug.assert(!!declarationFilePath || isJavaScript(referencedFile.fileName), "Declaration file is not present only for javascript files");
|
||||
declFileName = declarationFilePath || jsFilePath;
|
||||
// Get the declaration file path
|
||||
forEachExpectedEmitFile(host, getDeclFileName, referencedFile);
|
||||
}
|
||||
|
||||
declFileName = getRelativePathToDirectoryOrUrl(
|
||||
getDirectoryPath(normalizeSlashes(declarationFilePath)),
|
||||
declFileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ false);
|
||||
if (declFileName) {
|
||||
declFileName = getRelativePathToDirectoryOrUrl(
|
||||
getDirectoryPath(normalizeSlashes(declarationFilePath)),
|
||||
declFileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ false);
|
||||
|
||||
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
|
||||
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
|
||||
}
|
||||
return addedBundledEmitReference;
|
||||
|
||||
function getDeclFileName(emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
// Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path
|
||||
if (isBundledEmit && !addBundledFileReference) {
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.assert(!!emitFileNames.declarationFilePath || isJavaScript(referencedFile.fileName), "Declaration file is not present only for javascript files");
|
||||
declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath;
|
||||
addedBundledEmitReference = isBundledEmit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function writeDeclarationFile(declarationFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
|
||||
let emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFile);
|
||||
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
|
||||
let emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
|
||||
let emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath);
|
||||
if (!emitSkipped) {
|
||||
let declarationOutput = emitDeclarationResult.referencePathsOutput
|
||||
|
||||
@ -8131,7 +8131,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
if (declarationFilePath) {
|
||||
emitSkipped = writeDeclarationFile(declarationFilePath, isBundledEmit ? undefined : sourceFiles[0], host, resolver, emitterDiagnostics) || emitSkipped;
|
||||
emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1792,48 +1792,6 @@ namespace ts {
|
||||
declarationFilePath: string;
|
||||
}
|
||||
|
||||
export function getEmitFileNames(sourceFile: SourceFile, host: EmitHost): EmitFileNames {
|
||||
if (!isDeclarationFile(sourceFile)) {
|
||||
let options = host.getCompilerOptions();
|
||||
let jsFilePath: string;
|
||||
if (shouldEmitToOwnFile(sourceFile, options)) {
|
||||
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host,
|
||||
sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js");
|
||||
return {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath: !isJavaScript(sourceFile.fileName) ? getDeclarationEmitFilePath(jsFilePath, options) : undefined
|
||||
};
|
||||
}
|
||||
else if (options.outFile || options.out) {
|
||||
return getBundledEmitFileNames(options);
|
||||
}
|
||||
}
|
||||
return {
|
||||
jsFilePath: undefined,
|
||||
sourceMapFilePath: undefined,
|
||||
declarationFilePath: undefined
|
||||
};
|
||||
}
|
||||
|
||||
function getBundledEmitFileNames(options: CompilerOptions): EmitFileNames {
|
||||
let jsFilePath = options.outFile || options.out;
|
||||
|
||||
return {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath: getDeclarationEmitFilePath(jsFilePath, options)
|
||||
};
|
||||
}
|
||||
|
||||
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.sourceMap ? jsFilePath + ".map" : undefined;
|
||||
}
|
||||
|
||||
function getDeclarationEmitFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
|
||||
}
|
||||
|
||||
export function forEachExpectedEmitFile(host: EmitHost,
|
||||
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
|
||||
targetSourceFile?: SourceFile) {
|
||||
@ -1861,16 +1819,37 @@ namespace ts {
|
||||
}
|
||||
|
||||
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
|
||||
action(getEmitFileNames(sourceFile, host), [sourceFile], /*isBundledEmit*/false);
|
||||
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host,
|
||||
sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js");
|
||||
let emitFileNames: EmitFileNames = {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath: !isJavaScript(sourceFile.fileName) ? getDeclarationEmitFilePath(jsFilePath, options) : undefined
|
||||
};
|
||||
action(emitFileNames, [sourceFile], /*isBundledEmit*/false);
|
||||
}
|
||||
|
||||
function onBundledEmit(host: EmitHost) {
|
||||
let bundledSources = filter(host.getSourceFiles(),
|
||||
sourceFile => !shouldEmitToOwnFile(sourceFile, host.getCompilerOptions()) && !isDeclarationFile(sourceFile));
|
||||
let jsFilePath = options.outFile || options.out;
|
||||
let emitFileNames: EmitFileNames = {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath: getDeclarationEmitFilePath(jsFilePath, options)
|
||||
};
|
||||
if (bundledSources.length) {
|
||||
action(getBundledEmitFileNames(options), bundledSources, /*isBundledEmit*/true);
|
||||
action(emitFileNames, bundledSources, /*isBundledEmit*/true);
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.sourceMap ? jsFilePath + ".map" : undefined;
|
||||
}
|
||||
|
||||
function getDeclarationEmitFilePath(jsFilePath: string, options: CompilerOptions) {
|
||||
return options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasFile(sourceFiles: SourceFile[], fileName: string) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user