diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cd6525a6bc3..0be2549b969 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -326,27 +326,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let emitSkipped = false; let newLine = host.getNewLine(); - if (targetSourceFile === undefined) { - forEach(host.getSourceFiles(), sourceFile => { - if (shouldEmitToOwnFile(sourceFile, compilerOptions)) { - emitSkipped = emitFile(getEmitFileNames(sourceFile, host), sourceFile) || emitSkipped; - } - }); - - if (compilerOptions.outFile || compilerOptions.out) { - emitSkipped = emitFile(getBundledEmitFileNames(compilerOptions)) || emitSkipped; - } - } - else { - // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service) - if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) { - emitSkipped = emitFile(getEmitFileNames(targetSourceFile, host), targetSourceFile) || emitSkipped; - } - else if (!isDeclarationFile(targetSourceFile) && - (compilerOptions.outFile || compilerOptions.out)) { - emitSkipped = emitFile(getBundledEmitFileNames(compilerOptions)) || emitSkipped; - } - } + forEachExpectedEmitFile(host, emitFile, targetSourceFile); // Sort and make the unique list of diagnostics diagnostics = sortAndDeduplicateDiagnostics(diagnostics); @@ -476,7 +456,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitJavaScript(jsFilePath: string, sourceMapFilePath: string, root?: SourceFile) { + function emitJavaScript(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) { let writer = createTextWriter(newLine); let { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer; @@ -557,17 +537,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi initializeEmitterWithSourceMaps(); } - if (root) { - // Do not call emit directly. It does not set the currentSourceFile. - emitSourceFile(root); - } - else { - forEach(host.getSourceFiles(), sourceFile => { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - emitSourceFile(sourceFile); - } - }); - } + // Do not call emit directly. It does not set the currentSourceFile. + forEach(sourceFiles, emitSourceFile); writeLine(); writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM); @@ -1009,10 +980,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (compilerOptions.mapRoot) { sourceMapDir = normalizeSlashes(compilerOptions.mapRoot); - if (root) { // emitting single module file + if (!isBundledEmit) { // emitting single module file + Debug.assert(sourceFiles.length === 1); // For modules or multiple emit files the mapRoot will have directory structure like the sources // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(root, host, sourceMapDir)); + sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); } if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) { @@ -8151,18 +8123,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath}: { jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string }, sourceFile?: SourceFile) { + function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath}: { jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string }, + sourceFiles: SourceFile[], isBundledEmit: boolean) { // Make sure not to write js File and source map file if any of them cannot be written - let emitSkipped = host.isEmitBlocked(jsFilePath) || (sourceMapFilePath && host.isEmitBlocked(sourceMapFilePath)); - if (!emitSkipped) { - emitJavaScript(jsFilePath, sourceMapFilePath, sourceFile); + if (!host.isEmitBlocked(jsFilePath)) { + emitJavaScript(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + } + else { + emitSkipped = true; } if (declarationFilePath) { - emitSkipped = writeDeclarationFile(declarationFilePath, sourceFile, host, resolver, diagnostics) || emitSkipped; + emitSkipped = writeDeclarationFile(declarationFilePath, isBundledEmit ? undefined : sourceFiles[0], host, resolver, diagnostics) || emitSkipped; } - - return emitSkipped; } } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f17aa97f717..7440a6b5481 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1786,7 +1786,13 @@ namespace ts { return emitOutputFilePathWithoutExtension + extension; } - export function getEmitFileNames(sourceFile: SourceFile, host: EmitHost) { + export interface EmitFileNames { + jsFilePath: string; + sourceMapFilePath: string; + declarationFilePath: string; + } + + export function getEmitFileNames(sourceFile: SourceFile, host: EmitHost): EmitFileNames { if (!isDeclarationFile(sourceFile)) { let options = host.getCompilerOptions(); let jsFilePath: string; @@ -1810,7 +1816,7 @@ namespace ts { }; } - export function getBundledEmitFileNames(options: CompilerOptions) { + function getBundledEmitFileNames(options: CompilerOptions): EmitFileNames { let jsFilePath = options.outFile || options.out; return { @@ -1820,6 +1826,8 @@ namespace ts { }; } + + function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) { return options.sourceMap ? jsFilePath + ".map" : undefined; } @@ -1828,6 +1836,38 @@ namespace ts { return options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined; } + export function forEachExpectedEmitFile(host: EmitHost, + action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void, + targetSourceFile?: SourceFile) { + let options = host.getCompilerOptions(); + if (targetSourceFile === undefined) { + forEach(host.getSourceFiles(), sourceFile => { + if (shouldEmitToOwnFile(sourceFile, options)) { + action(getEmitFileNames(sourceFile, host), [sourceFile], /*isBundledEmit*/false); + } + }); + + if (options.outFile || options.out) { + action(getBundledEmitFileNames(options), getBundledEmitSourceFiles(host), /*isBundledEmit*/true); + } + } + else { + // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service) + if (shouldEmitToOwnFile(targetSourceFile, options)) { + action(getEmitFileNames(targetSourceFile, host), [targetSourceFile], /*isBundledEmit*/false); + } + else if (!isDeclarationFile(targetSourceFile) && + (options.outFile || options.out)) { + action(getBundledEmitFileNames(options), getBundledEmitSourceFiles(host), /*isBundledEmit*/true); + } + } + + function getBundledEmitSourceFiles(host: EmitHost): SourceFile[] { + return filter(host.getSourceFiles(), + sourceFile => !shouldEmitToOwnFile(sourceFile, host.getCompilerOptions()) && !isDeclarationFile(sourceFile)); + } + } + export function hasFile(sourceFiles: SourceFile[], fileName: string) { return forEach(sourceFiles, file => file.fileName === fileName); }