diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6c36198a414ad..3ee49e43cbcf4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -431,7 +431,7 @@ namespace ts { const moduleKind = getEmitModuleKind(printerOptions); const bundledHelpers = createMap(); - let currentSourceFile!: SourceFile; + let currentSourceFile: SourceFile | undefined; let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. let generatedNames: Map; // Set of names generated by the NameGenerator. @@ -604,11 +604,13 @@ namespace ts { pipelinePhase(hint, node); } - function setSourceFile(sourceFile: SourceFile) { + function setSourceFile(sourceFile: SourceFile | undefined) { currentSourceFile = sourceFile; currentLineMap = undefined; detachedCommentsInfo = undefined; - setSourceMapSource(sourceFile); + if (sourceFile) { + setSourceMapSource(sourceFile); + } } function setWriter(_writer: EmitTextWriter | undefined, _sourceMapGenerator: SourceMapGenerator | undefined) { @@ -635,7 +637,7 @@ namespace ts { } function getCurrentLineMap() { - return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile)); + return currentLineMap || (currentLineMap = getLineStarts(currentSourceFile!)); } function emit(node: Node | undefined) { @@ -1130,7 +1132,7 @@ namespace ts { const numNodes = bundle ? bundle.sourceFiles.length : 1; for (let i = 0; i < numNodes; i++) { const currentNode = bundle ? bundle.sourceFiles[i] : node; - const sourceFile = isSourceFile(currentNode) ? currentNode : currentSourceFile; + const sourceFile = isSourceFile(currentNode) ? currentNode : currentSourceFile!; const shouldSkip = printerOptions.noEmitHelpers || getExternalHelpersModuleName(sourceFile) !== undefined; const shouldBundle = isSourceFile(currentNode) && !isOwnFileEmit; const helpers = getEmitHelpers(currentNode); @@ -1638,7 +1640,7 @@ namespace ts { } const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - const allowTrailingComma = currentSourceFile.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; + const allowTrailingComma = currentSourceFile!.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile!) ? ListFormat.AllowTrailingComma : ListFormat.None; emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); if (indentedFlag) { @@ -1651,7 +1653,7 @@ namespace ts { let indentAfterDot = false; if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { const dotRangeStart = node.expression.end; - const dotRangeEnd = skipTrivia(currentSourceFile.text, node.expression.end) + 1; + const dotRangeEnd = skipTrivia(currentSourceFile!.text, node.expression.end) + 1; const dotToken = createToken(SyntaxKind.DotToken); dotToken.pos = dotRangeStart; dotToken.end = dotRangeEnd; @@ -1937,7 +1939,7 @@ namespace ts { emitExpression(node.expression); // Emit semicolon in non json files // or if json file that created synthesized expression(eg.define expression statement when --out and amd code generation) - if (!isJsonSourceFile(currentSourceFile) || nodeIsSynthesized(node.expression)) { + if (!isJsonSourceFile(currentSourceFile!) || nodeIsSynthesized(node.expression)) { writeTrailingSemicolon(); } } @@ -2057,10 +2059,10 @@ namespace ts { const isSimilarNode = node && node.kind === contextNode.kind; const startPos = pos; if (isSimilarNode) { - pos = skipTrivia(currentSourceFile.text, pos); + pos = skipTrivia(currentSourceFile!.text, pos); } if (emitLeadingCommentsOfPosition && isSimilarNode && contextNode.pos !== startPos) { - const needsIndent = indentLeading && !positionsAreOnSameLine(startPos, pos, currentSourceFile); + const needsIndent = indentLeading && !positionsAreOnSameLine(startPos, pos, currentSourceFile!); if (needsIndent) { increaseIndent(); } @@ -2231,7 +2233,7 @@ namespace ts { return false; } - if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) { + if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile!)) { return false; } @@ -2644,7 +2646,7 @@ namespace ts { // treat synthesized nodes as located on the same line for emit purposes nodeIsSynthesized(parentNode) || nodeIsSynthesized(statements[0]) || - rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) + rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile!) ); let format = ListFormat.CaseOrDefaultClauseStatements; @@ -2998,6 +3000,7 @@ namespace ts { setSourceFile(sourceFile); emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives); } + setSourceFile(undefined); } } @@ -3488,13 +3491,13 @@ namespace ts { const firstChild = children[0]; if (firstChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); + return !rangeIsOnSingleLine(parentNode, currentSourceFile!); } else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { return synthesizedNodeStartsOnNewLine(firstChild, format); } else { - return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); + return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile!); } } else { @@ -3514,7 +3517,7 @@ namespace ts { return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); } else { - return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); + return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile!); } } else { @@ -3533,13 +3536,13 @@ namespace ts { const lastChild = lastOrUndefined(children); if (lastChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); + return !rangeIsOnSingleLine(parentNode, currentSourceFile!); } else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { return synthesizedNodeStartsOnNewLine(lastChild, format); } else { - return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); + return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile!); } } else { @@ -3573,12 +3576,12 @@ namespace ts { return !nodeIsSynthesized(parent) && !nodeIsSynthesized(node1) && !nodeIsSynthesized(node2) - && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); + && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile!); } function isEmptyBlock(block: BlockLike) { return block.statements.length === 0 - && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); + && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile!); } function skipSynthesizedParentheses(node: Node) { @@ -3603,7 +3606,7 @@ namespace ts { return node.text; } - return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); + return getSourceTextOfNodeFromSourceFile(currentSourceFile!, node, includeTrivia); } function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined): string { @@ -3619,7 +3622,7 @@ namespace ts { } } - return getLiteralText(node, currentSourceFile, neverAsciiEscape); + return getLiteralText(node, currentSourceFile!, neverAsciiEscape); } /** @@ -4181,7 +4184,7 @@ namespace ts { } function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { - if (!shouldWriteComment(currentSourceFile.text, commentPos)) return; + if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return; if (!hasWrittenComment) { emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos); hasWrittenComment = true; @@ -4189,7 +4192,7 @@ namespace ts { // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space emitPos(commentPos); - writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { @@ -4213,14 +4216,14 @@ namespace ts { } function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { - if (!shouldWriteComment(currentSourceFile.text, commentPos)) return; + if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return; // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ if (!writer.isAtStartOfLine()) { writer.writeSpace(" "); } emitPos(commentPos); - writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { @@ -4241,7 +4244,7 @@ namespace ts { // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space emitPos(commentPos); - writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { @@ -4285,11 +4288,11 @@ namespace ts { detachedCommentsInfo = undefined; } - forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos); + forEachLeadingCommentRange(currentSourceFile!.text, pos, cb, /*state*/ pos); } function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) { - const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled); + const currentDetachedCommentInfo = emitDetachedComments(currentSourceFile!.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -4301,7 +4304,7 @@ namespace ts { } function emitComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { - if (!shouldWriteComment(currentSourceFile.text, commentPos)) return; + if (!shouldWriteComment(currentSourceFile!.text, commentPos)) return; emitPos(commentPos); writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); emitPos(commentEnd); @@ -4313,7 +4316,7 @@ namespace ts { * @return true if the comment is a triple-slash comment else false */ function isTripleSlashComment(commentPos: number, commentEnd: number) { - return isRecognizedTripleSlashComment(currentSourceFile.text, commentPos, commentEnd); + return isRecognizedTripleSlashComment(currentSourceFile!.text, commentPos, commentEnd); } // Source Maps @@ -4377,7 +4380,7 @@ namespace ts { return; } - const { line: sourceLine, character: sourceCharacter } = getLineAndCharacterOfPosition(currentSourceFile, pos); + const { line: sourceLine, character: sourceCharacter } = getLineAndCharacterOfPosition(currentSourceFile!, pos); sourceMapGenerator!.addMapping( writer.getLine(), writer.getColumn(), diff --git a/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.js b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.js new file mode 100644 index 0000000000000..f2e5bc636b498 --- /dev/null +++ b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/amdModuleBundleNoDuplicateDeclarationEmitComments.ts] //// + +//// [file1.ts] +/// +export class Foo {} +//// [file2.ts] +/// +export class Bar {} + +//// [out.js] +define("mynamespace::SomeModuleA", ["require", "exports"], function (require, exports) { + "use strict"; + exports.__esModule = true; + /// + var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; + }()); + exports.Foo = Foo; +}); +define("mynamespace::SomeModuleB", ["require", "exports"], function (require, exports) { + "use strict"; + exports.__esModule = true; + /// + var Bar = /** @class */ (function () { + function Bar() { + } + return Bar; + }()); + exports.Bar = Bar; +}); + + +//// [out.d.ts] +/// +declare module "mynamespace::SomeModuleA" { + export class Foo { + } +} +/// +declare module "mynamespace::SomeModuleB" { + export class Bar { + } +} diff --git a/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.symbols b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.symbols new file mode 100644 index 0000000000000..69eaee002f24a --- /dev/null +++ b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/file1.ts === +/// +export class Foo {} +>Foo : Symbol(Foo, Decl(file1.ts, 0, 0)) + +=== tests/cases/compiler/file2.ts === +/// +export class Bar {} +>Bar : Symbol(Bar, Decl(file2.ts, 0, 0)) + diff --git a/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.types b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.types new file mode 100644 index 0000000000000..d90ff85e5fbed --- /dev/null +++ b/tests/baselines/reference/amdModuleBundleNoDuplicateDeclarationEmitComments.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/file1.ts === +/// +export class Foo {} +>Foo : Foo + +=== tests/cases/compiler/file2.ts === +/// +export class Bar {} +>Bar : Bar + diff --git a/tests/cases/compiler/amdModuleBundleNoDuplicateDeclarationEmitComments.ts b/tests/cases/compiler/amdModuleBundleNoDuplicateDeclarationEmitComments.ts new file mode 100644 index 0000000000000..ac185a891177c --- /dev/null +++ b/tests/cases/compiler/amdModuleBundleNoDuplicateDeclarationEmitComments.ts @@ -0,0 +1,9 @@ +//@module: amd +// @declaration: true +// @outFile: ./out.js +// @filename: file1.ts +/// +export class Foo {} +// @filename: file2.ts +/// +export class Bar {} \ No newline at end of file