diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cb5eb864660..d0947b35693 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -832,7 +832,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(", "); } } - emitNode(nodes[start + i]); + let node = nodes[start + i]; + // This emitting is to make sure we emit following comment properly + // ...(x, /comment1/ y)... + // ^ => node.pos + // "comment1" is not considered leading comment for node-y but rather + // considered as trailing comment of the previous node. + emitTrailingCommentsOfPosition(node.pos); + emitNode(node); leadingComma = true; } if (trailingComma) { @@ -1976,6 +1983,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyAssignment(node: PropertyDeclaration) { emit(node.name); write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /comment1/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + emitTrailingCommentsOfPosition(node.initializer.pos); emit(node.initializer); } @@ -3617,8 +3632,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return emitOnlyPinnedOrTripleSlashComments(node); } - if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { - // Methods will emit the comments as part of emitting method declaration + if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature && + node.parent && node.parent.kind !== SyntaxKind.PropertyAssignment && + node.parent.kind !== SyntaxKind.CallExpression) { + // 1. Methods will emit the comments as part of emitting method declaration + + // 2. If the function is a property of object literal, emitting leading-comments + // is done by emitNodeWithoutSourceMap which then call this function. + // In particular, we would like to avoid emit comments twice in following case: + // For example: + // var obj = { + // id: + // /*comment*/ () => void + // } + + // 3. If the function is an argument in call expression, emitting of comments will be + // taken care of in emit list of arguments inside of emitCallexpression emitLeadingComments(node); } @@ -6925,6 +6954,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); } + /** + * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: + * x, /comment1/ y + * ^ => pos; the function will emit "comment1" in the emitJS + */ + function emitTrailingCommentsOfPosition(pos: number) { + let trailingComments = filterComments(getTrailingCommentRanges(currentSourceFile.text, pos), /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments); + + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ + emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + } + function emitLeadingCommentsOfPosition(pos: number) { let leadingComments: CommentRange[]; if (hasDetachedComments(pos)) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 312a3666757..5d24db35762 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -381,24 +381,12 @@ namespace ts { } export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { - // If parameter/type parameter, the prev token trailing comments are part of this node too - if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) { - // e.g. (/** blah */ a, /** blah */ b); - - // e.g.: ( - // /** blah */ a, - // /** blah */ b); - return concatenate( - getTrailingCommentRanges(sourceFileOfNode.text, node.pos), - getLeadingCommentRanges(sourceFileOfNode.text, node.pos)); - } - else { - return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); - } + return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { - return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment); + let commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ? concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : getLeadingCommentRangesOfNode(node, sourceFileOfNode); + return filter(commentRanges, isJsDocComment); function isJsDocComment(comment: CommentRange) { // True if the comment starts with '/**' but not if it is '/**/'