Under jsx: preserve, actually preserve expressions which contain only comments (#41757)

* Under jsx: preserve, actually preserve expressions which contain only comments

* Even better best effort comment preservation in JSX comments
This commit is contained in:
Wesley Wigham
2020-12-18 11:42:33 -08:00
committed by GitHub
parent caebbe6714
commit c3ff0d4c17
40 changed files with 1034 additions and 32 deletions

View File

@@ -2864,7 +2864,8 @@ namespace ts {
}
pos = writeTokenText(token, writer, pos);
if (isSimilarNode && contextNode.end !== pos) {
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true);
const isJsxExprContext = contextNode.kind === SyntaxKind.JsxExpression;
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ !isJsxExprContext, /*forceNoNewline*/ isJsxExprContext);
}
return pos;
}
@@ -3421,12 +3422,35 @@ namespace ts {
writePunctuation("}");
}
function hasTrailingCommentsAtPosition(pos: number) {
let result = false;
forEachTrailingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true);
return result;
}
function hasLeadingCommentsAtPosition(pos: number) {
let result = false;
forEachLeadingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true);
return result;
}
function hasCommentsAtPosition(pos: number) {
return hasTrailingCommentsAtPosition(pos) || hasLeadingCommentsAtPosition(pos);
}
function emitJsxExpression(node: JsxExpression) {
if (node.expression) {
writePunctuation("{");
if (node.expression || (!commentsDisabled && !nodeIsSynthesized(node) && hasCommentsAtPosition(node.pos))) { // preserve empty expressions if they contain comments!
const isMultiline = currentSourceFile && !nodeIsSynthesized(node) && getLineAndCharacterOfPosition(currentSourceFile, node.pos).line !== getLineAndCharacterOfPosition(currentSourceFile, node.end).line;
if (isMultiline) {
writer.increaseIndent();
}
const end = emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node);
emit(node.dotDotDotToken);
emitExpression(node.expression);
writePunctuation("}");
emitTokenWithComment(SyntaxKind.CloseBraceToken, node.expression?.end || end, writePunctuation, node);
if (isMultiline) {
writer.decreaseIndent();
}
}
}
@@ -5274,15 +5298,27 @@ namespace ts {
}
}
function emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean) {
function emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean, forceNoNewline?: boolean) {
if (commentsDisabled) {
return;
}
enterComment();
forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : emitTrailingCommentOfPosition);
forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : forceNoNewline ? emitTrailingCommentOfPositionNoNewline : emitTrailingCommentOfPosition);
exitComment();
}
function emitTrailingCommentOfPositionNoNewline(commentPos: number, commentEnd: number, kind: SyntaxKind) {
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
emitPos(commentPos);
writeCommentRange(currentSourceFile!.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
if (kind === SyntaxKind.SingleLineCommentTrivia) {
writer.writeLine(); // still write a newline for single-line comments, so closing tokens aren't written on the same line
}
}
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space

View File

@@ -1790,7 +1790,7 @@ namespace ts {
const name = importDeclaration.propertyName || importDeclaration.name;
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent),
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration),
factory.cloneNode(name)
),
/*location*/ node

View File

@@ -1678,7 +1678,7 @@ namespace ts {
factory.createPropertyAssignment(
factory.cloneNode(name),
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent),
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration),
factory.cloneNode(importDeclaration.propertyName || importDeclaration.name)
),
),
@@ -1747,7 +1747,7 @@ namespace ts {
else if (isImportSpecifier(importDeclaration)) {
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent),
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration),
factory.cloneNode(importDeclaration.propertyName || importDeclaration.name)
),
/*location*/ node