Skip to content

Commit d7d0434

Browse files
committed
Move ASI-blocking parens out of ts transform
1 parent 0314c4a commit d7d0434

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/compiler/emitter.ts

+43-3
Original file line numberDiff line numberDiff line change
@@ -2747,7 +2747,7 @@ namespace ts {
27472747
function emitYieldExpression(node: YieldExpression) {
27482748
emitTokenWithComment(SyntaxKind.YieldKeyword, node.pos, writeKeyword, node);
27492749
emit(node.asteriskToken);
2750-
emitExpressionWithLeadingSpace(node.expression, parenthesizer.parenthesizeExpressionForDisallowedComma);
2750+
emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsiAndDisallowedComma);
27512751
}
27522752

27532753
function emitSpreadElement(node: SpreadElement) {
@@ -2971,9 +2971,49 @@ namespace ts {
29712971
return pos;
29722972
}
29732973

2974+
function commentWillEmitNewLine(node: CommentRange) {
2975+
return node.kind === SyntaxKind.SingleLineCommentTrivia || !!node.hasTrailingNewLine;
2976+
}
2977+
2978+
function willEmitLeadingNewLine(node: Expression): boolean {
2979+
if (!currentSourceFile) return false;
2980+
if (some(getLeadingCommentRanges(currentSourceFile.text, node.pos), commentWillEmitNewLine)) return true;
2981+
if (some(getSyntheticLeadingComments(node), commentWillEmitNewLine)) return true;
2982+
if (isPartiallyEmittedExpression(node)) {
2983+
if (node.pos !== node.expression.pos) {
2984+
if (some(getTrailingCommentRanges(currentSourceFile.text, node.expression.pos), commentWillEmitNewLine)) return true;
2985+
}
2986+
return willEmitLeadingNewLine(node.expression);
2987+
}
2988+
return false;
2989+
}
2990+
2991+
/**
2992+
* Wraps an expression in parens if we would emit a leading comment that would introduce a line separator
2993+
* between the node and its parent.
2994+
*/
2995+
function parenthesizeExpressionForNoAsi(node: Expression) {
2996+
if (!commentsDisabled && isPartiallyEmittedExpression(node) && willEmitLeadingNewLine(node)) {
2997+
const parseNode = getParseTreeNode(node);
2998+
if (parseNode && isParenthesizedExpression(parseNode)) {
2999+
// If the original node was a parenthesized expression, restore it to preserve comment and source map emit
3000+
const parens = factory.createParenthesizedExpression(node.expression);
3001+
setOriginalNode(parens, node);
3002+
setTextRange(parens, parseNode);
3003+
return parens;
3004+
}
3005+
return factory.createParenthesizedExpression(node);
3006+
}
3007+
return node;
3008+
}
3009+
3010+
function parenthesizeExpressionForNoAsiAndDisallowedComma(node: Expression) {
3011+
return parenthesizeExpressionForNoAsi(parenthesizer.parenthesizeExpressionForDisallowedComma(node));
3012+
}
3013+
29743014
function emitReturnStatement(node: ReturnStatement) {
29753015
emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, writeKeyword, /*contextNode*/ node);
2976-
emitExpressionWithLeadingSpace(node.expression);
3016+
emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsi);
29773017
writeTrailingSemicolon();
29783018
}
29793019

@@ -3005,7 +3045,7 @@ namespace ts {
30053045

30063046
function emitThrowStatement(node: ThrowStatement) {
30073047
emitTokenWithComment(SyntaxKind.ThrowKeyword, node.pos, writeKeyword, node);
3008-
emitExpressionWithLeadingSpace(node.expression);
3048+
emitExpressionWithLeadingSpace(parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsi);
30093049
writeTrailingSemicolon();
30103050
}
30113051

src/compiler/transformers/ts.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -2237,11 +2237,10 @@ namespace ts {
22372237
// we can safely elide the parentheses here, as a new synthetic
22382238
// ParenthesizedExpression will be inserted if we remove parentheses too
22392239
// aggressively.
2240-
// HOWEVER - if there are leading comments on the expression itself, to handle ASI
2241-
// correctly for return and throw, we must keep the parenthesis
2242-
if (length(getLeadingCommentRangesOfNode(expression, currentSourceFile))) {
2243-
return factory.updateParenthesizedExpression(node, expression);
2244-
}
2240+
//
2241+
// If there are leading comments on the expression itself, the emitter will handle ASI
2242+
// for return, throw, and yield by re-introducing parenthesis during emit on an as-need
2243+
// basis.
22452244
return factory.createPartiallyEmittedExpression(expression, node);
22462245
}
22472246

0 commit comments

Comments
 (0)