Skip to content

Commit 2b582a0

Browse files
committed
Simplifty declaration emitter logic by using forEachExpectedEmitFile
1 parent 06bf08c commit 2b582a0

3 files changed

Lines changed: 99 additions & 120 deletions

File tree

src/compiler/declarationEmitter.ts

Lines changed: 75 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,12 @@ namespace ts {
3636
return declarationDiagnostics.getDiagnostics(targetSourceFile.fileName);
3737

3838
function getDeclarationDiagnosticsFromFile({ declarationFilePath }, sources: SourceFile[], isBundledEmit: boolean) {
39-
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, !isBundledEmit ? targetSourceFile : undefined);
39+
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit);
4040
}
4141
}
4242

43-
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string, root?: SourceFile): DeclarationEmit {
43+
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
44+
sourceFiles: SourceFile[], isBundledEmit: boolean): DeclarationEmit {
4445
let newLine = host.getNewLine();
4546
let compilerOptions = host.getCompilerOptions();
4647

@@ -67,67 +68,48 @@ namespace ts {
6768
// and we could be collecting these paths from multiple files into single one with --out option
6869
let referencePathsOutput = "";
6970

70-
if (root) {
71-
// Emitting just a single file, so emit references in this file only
72-
if (!compilerOptions.noResolve) {
73-
let addedGlobalFileReference = false;
74-
forEach(root.referencedFiles, fileReference => {
75-
let referencedFile = tryResolveScriptReference(host, root, fileReference);
76-
77-
// All the references that are not going to be part of same file
78-
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
79-
shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
80-
!addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
81-
82-
writeReferencePath(referencedFile);
83-
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
84-
addedGlobalFileReference = true;
85-
}
86-
}
87-
});
88-
}
89-
90-
emitSourceFile(root);
91-
92-
// create asynchronous output for the importDeclarations
93-
if (moduleElementDeclarationEmitInfo.length) {
94-
let oldWriter = writer;
95-
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
96-
if (aliasEmitInfo.isVisible) {
97-
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
98-
createAndSetNewTextWriterWithSymbolWriter();
99-
Debug.assert(aliasEmitInfo.indent === 0);
100-
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
101-
aliasEmitInfo.asynchronousOutput = writer.getText();
102-
}
103-
});
104-
setWriter(oldWriter);
105-
}
106-
}
107-
else {
108-
// Emit references corresponding to this file
109-
let emittedReferencedFiles: SourceFile[] = [];
110-
forEach(host.getSourceFiles(), sourceFile => {
111-
if (!isExternalModuleOrDeclarationFile(sourceFile) && !isJavaScript(sourceFile.fileName)) {
112-
// Check what references need to be added
113-
if (!compilerOptions.noResolve) {
114-
forEach(sourceFile.referencedFiles, fileReference => {
115-
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
116-
117-
// If the reference file is a declaration file or an external module, emit that reference
118-
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
119-
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
120-
121-
writeReferencePath(referencedFile);
122-
emittedReferencedFiles.push(referencedFile);
71+
// Emit references corresponding to each file
72+
let emittedReferencedFiles: SourceFile[] = [];
73+
let addedGlobalFileReference = false;
74+
forEach(sourceFiles, sourceFile => {
75+
if (!isJavaScript(sourceFile.fileName)) {
76+
// Check what references need to be added
77+
if (!compilerOptions.noResolve) {
78+
forEach(sourceFile.referencedFiles, fileReference => {
79+
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
80+
81+
// Emit reference in dts, if the file reference was not already emitted
82+
if (referencedFile && !contains(emittedReferencedFiles, referencedFile)) {
83+
// Add a reference to generated dts file,
84+
// global file reference is added only
85+
// - if it is not bundled emit (because otherwise it would be self reference)
86+
// - and it is not already added
87+
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
88+
addedGlobalFileReference = true;
12389
}
124-
});
125-
}
90+
emittedReferencedFiles.push(referencedFile);
91+
}
92+
});
93+
}
12694

127-
emitSourceFile(sourceFile);
95+
emitSourceFile(sourceFile);
96+
97+
// create asynchronous output for the importDeclarations
98+
if (moduleElementDeclarationEmitInfo.length) {
99+
let oldWriter = writer;
100+
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
101+
if (aliasEmitInfo.isVisible) {
102+
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
103+
createAndSetNewTextWriterWithSymbolWriter();
104+
Debug.assert(aliasEmitInfo.indent === 0);
105+
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
106+
aliasEmitInfo.asynchronousOutput = writer.getText();
107+
}
108+
});
109+
setWriter(oldWriter);
128110
}
129-
});
130-
}
111+
}
112+
});
131113

132114
return {
133115
reportedDeclarationError,
@@ -1592,33 +1574,51 @@ namespace ts {
15921574
}
15931575
}
15941576

1595-
function writeReferencePath(referencedFile: SourceFile) {
1577+
/**
1578+
* Adds the reference to referenced file, returns true if global file reference was emitted
1579+
* @param referencedFile
1580+
* @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not
1581+
*/
1582+
function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean): boolean {
15961583
let declFileName: string;
1597-
if (referencedFile.flags & NodeFlags.DeclarationFile) {
1584+
let addedBundledEmitReference = false;
1585+
if (isDeclarationFile(referencedFile)) {
15981586
// Declaration file, use declaration file name
15991587
declFileName = referencedFile.fileName;
16001588
}
16011589
else {
1602-
// declaration file name
1603-
let { declarationFilePath, jsFilePath } = getEmitFileNames(referencedFile, host);
1604-
Debug.assert(!!declarationFilePath || isJavaScript(referencedFile.fileName), "Declaration file is not present only for javascript files");
1605-
declFileName = declarationFilePath || jsFilePath;
1590+
// Get the declaration file path
1591+
forEachExpectedEmitFile(host, getDeclFileName, referencedFile);
16061592
}
16071593

1608-
declFileName = getRelativePathToDirectoryOrUrl(
1609-
getDirectoryPath(normalizeSlashes(declarationFilePath)),
1610-
declFileName,
1611-
host.getCurrentDirectory(),
1612-
host.getCanonicalFileName,
1613-
/*isAbsolutePathAnUrl*/ false);
1594+
if (declFileName) {
1595+
declFileName = getRelativePathToDirectoryOrUrl(
1596+
getDirectoryPath(normalizeSlashes(declarationFilePath)),
1597+
declFileName,
1598+
host.getCurrentDirectory(),
1599+
host.getCanonicalFileName,
1600+
/*isAbsolutePathAnUrl*/ false);
16141601

1615-
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
1602+
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
1603+
}
1604+
return addedBundledEmitReference;
1605+
1606+
function getDeclFileName(emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) {
1607+
// Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path
1608+
if (isBundledEmit && !addBundledFileReference) {
1609+
return;
1610+
}
1611+
1612+
Debug.assert(!!emitFileNames.declarationFilePath || isJavaScript(referencedFile.fileName), "Declaration file is not present only for javascript files");
1613+
declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath;
1614+
addedBundledEmitReference = isBundledEmit;
1615+
}
16161616
}
16171617
}
16181618

16191619
/* @internal */
1620-
export function writeDeclarationFile(declarationFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
1621-
let emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFile);
1620+
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
1621+
let emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
16221622
let emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath);
16231623
if (!emitSkipped) {
16241624
let declarationOutput = emitDeclarationResult.referencePathsOutput

src/compiler/emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8131,7 +8131,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
81318131
}
81328132

81338133
if (declarationFilePath) {
8134-
emitSkipped = writeDeclarationFile(declarationFilePath, isBundledEmit ? undefined : sourceFiles[0], host, resolver, emitterDiagnostics) || emitSkipped;
8134+
emitSkipped = writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped;
81358135
}
81368136
}
81378137
}

src/compiler/utilities.ts

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,48 +1792,6 @@ namespace ts {
17921792
declarationFilePath: string;
17931793
}
17941794

1795-
export function getEmitFileNames(sourceFile: SourceFile, host: EmitHost): EmitFileNames {
1796-
if (!isDeclarationFile(sourceFile)) {
1797-
let options = host.getCompilerOptions();
1798-
let jsFilePath: string;
1799-
if (shouldEmitToOwnFile(sourceFile, options)) {
1800-
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host,
1801-
sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js");
1802-
return {
1803-
jsFilePath,
1804-
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
1805-
declarationFilePath: !isJavaScript(sourceFile.fileName) ? getDeclarationEmitFilePath(jsFilePath, options) : undefined
1806-
};
1807-
}
1808-
else if (options.outFile || options.out) {
1809-
return getBundledEmitFileNames(options);
1810-
}
1811-
}
1812-
return {
1813-
jsFilePath: undefined,
1814-
sourceMapFilePath: undefined,
1815-
declarationFilePath: undefined
1816-
};
1817-
}
1818-
1819-
function getBundledEmitFileNames(options: CompilerOptions): EmitFileNames {
1820-
let jsFilePath = options.outFile || options.out;
1821-
1822-
return {
1823-
jsFilePath,
1824-
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
1825-
declarationFilePath: getDeclarationEmitFilePath(jsFilePath, options)
1826-
};
1827-
}
1828-
1829-
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
1830-
return options.sourceMap ? jsFilePath + ".map" : undefined;
1831-
}
1832-
1833-
function getDeclarationEmitFilePath(jsFilePath: string, options: CompilerOptions) {
1834-
return options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
1835-
}
1836-
18371795
export function forEachExpectedEmitFile(host: EmitHost,
18381796
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
18391797
targetSourceFile?: SourceFile) {
@@ -1861,16 +1819,37 @@ namespace ts {
18611819
}
18621820

18631821
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
1864-
action(getEmitFileNames(sourceFile, host), [sourceFile], /*isBundledEmit*/false);
1822+
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host,
1823+
sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js");
1824+
let emitFileNames: EmitFileNames = {
1825+
jsFilePath,
1826+
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
1827+
declarationFilePath: !isJavaScript(sourceFile.fileName) ? getDeclarationEmitFilePath(jsFilePath, options) : undefined
1828+
};
1829+
action(emitFileNames, [sourceFile], /*isBundledEmit*/false);
18651830
}
18661831

18671832
function onBundledEmit(host: EmitHost) {
18681833
let bundledSources = filter(host.getSourceFiles(),
18691834
sourceFile => !shouldEmitToOwnFile(sourceFile, host.getCompilerOptions()) && !isDeclarationFile(sourceFile));
1835+
let jsFilePath = options.outFile || options.out;
1836+
let emitFileNames: EmitFileNames = {
1837+
jsFilePath,
1838+
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
1839+
declarationFilePath: getDeclarationEmitFilePath(jsFilePath, options)
1840+
};
18701841
if (bundledSources.length) {
1871-
action(getBundledEmitFileNames(options), bundledSources, /*isBundledEmit*/true);
1842+
action(emitFileNames, bundledSources, /*isBundledEmit*/true);
18721843
}
18731844
}
1845+
1846+
function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
1847+
return options.sourceMap ? jsFilePath + ".map" : undefined;
1848+
}
1849+
1850+
function getDeclarationEmitFilePath(jsFilePath: string, options: CompilerOptions) {
1851+
return options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
1852+
}
18741853
}
18751854

18761855
export function hasFile(sourceFiles: SourceFile[], fileName: string) {

0 commit comments

Comments
 (0)