Skip to content

Commit 3d2cd43

Browse files
committed
Offload all jsx text indentation handling to indentMultilineCommentOrJsxText
1 parent ff1a1aa commit 3d2cd43

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

src/services/formatting/formatting.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -501,9 +501,6 @@ namespace ts.formatting {
501501
else if (SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile)) {
502502
return { indentation: parentDynamicIndentation.getIndentation(), delta };
503503
}
504-
else if (SmartIndenter.isJSXClosingWithMultiLineText(parent, node, startLine, sourceFile)) {
505-
return { indentation: parentDynamicIndentation.getIndentation(), delta };
506-
}
507504
else {
508505
return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta };
509506
}
@@ -652,6 +649,11 @@ namespace ts.formatting {
652649
if (tokenInfo.token.end > node.end) {
653650
break;
654651
}
652+
if (node.kind === SyntaxKind.JsxText) {
653+
// Intentation rules for jsx text are handled by `indentMultilineCommentOrJsxText` inside `processChildNode`; just fastforward past it here
654+
formattingScanner.advance();
655+
continue;
656+
}
655657
consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node);
656658
}
657659

@@ -741,7 +743,20 @@ namespace ts.formatting {
741743
processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
742744
if (child.kind === SyntaxKind.JsxText) {
743745
const range: TextRange = { pos: child.getStart(), end: child.getEnd() };
744-
indentMultilineCommentOrJsxText(range, childIndentation.indentation, /*firstLineIsIndented*/ true, /*indentFinalLine*/ false);
746+
if (range.pos !== range.end) { // don't indent zero-width jsx text
747+
const siblings = parent.getChildren(sourceFile);
748+
const currentNode = find(siblings, arg => arg.pos === child.pos);
749+
const currentIndex = siblings.indexOf(currentNode!);
750+
const previousNode = siblings[currentIndex - 1];
751+
if (previousNode) {
752+
// The jsx text needs no indentation whatsoever if it ends on the same line the previous sibling ends on
753+
if (sourceFile.getLineAndCharacterOfPosition(range.end).line !== sourceFile.getLineAndCharacterOfPosition(previousNode.end).line) {
754+
// The first line is (already) "indented" if the text starts on the same line as the previous sibling element ends on
755+
const firstLineIsIndented = sourceFile.getLineAndCharacterOfPosition(range.pos).line === sourceFile.getLineAndCharacterOfPosition(previousNode.end).line;
756+
indentMultilineCommentOrJsxText(range, childIndentation.indentation, firstLineIsIndented, /*indentFinalLine*/ false, /*jsxStyle*/ true);
757+
}
758+
}
759+
}
745760
}
746761

747762
childContextNode = node;
@@ -1041,7 +1056,7 @@ namespace ts.formatting {
10411056
return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length);
10421057
}
10431058

1044-
function indentMultilineCommentOrJsxText(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true) {
1059+
function indentMultilineCommentOrJsxText(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true, jsxTextStyleIndent?: boolean) {
10451060
// split comment in lines
10461061
let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
10471062
const endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
@@ -1072,7 +1087,7 @@ namespace ts.formatting {
10721087
const nonWhitespaceColumnInFirstPart =
10731088
SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
10741089

1075-
if (indentation === nonWhitespaceColumnInFirstPart.column) {
1090+
if (indentation === nonWhitespaceColumnInFirstPart.column && !jsxTextStyleIndent) {
10761091
return;
10771092
}
10781093

@@ -1083,14 +1098,19 @@ namespace ts.formatting {
10831098
}
10841099

10851100
// shift all parts on the delta size
1086-
const delta = indentation - nonWhitespaceColumnInFirstPart.column;
1101+
let delta = indentation - nonWhitespaceColumnInFirstPart.column;
10871102
for (let i = startIndex; i < parts.length; i++ , startLine++) {
10881103
const startLinePos = getStartPositionOfLine(startLine, sourceFile);
10891104
const nonWhitespaceCharacterAndColumn =
10901105
i === 0
10911106
? nonWhitespaceColumnInFirstPart
10921107
: SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
1093-
1108+
if (jsxTextStyleIndent) {
1109+
// skip adding indentation to blank lines
1110+
if (isLineBreak(sourceFile.text.charCodeAt(getStartPositionOfLine(startLine, sourceFile)))) continue;
1111+
// reset delta on every line
1112+
delta = indentation - nonWhitespaceCharacterAndColumn.column;
1113+
}
10941114
const newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
10951115
if (newIndentation > 0) {
10961116
const indentationString = getIndentationString(newIndentation, options);

src/services/formatting/smartIndenter.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -343,24 +343,6 @@ namespace ts.formatting {
343343
return false;
344344
}
345345

346-
export function isJSXClosingWithMultiLineText(parent: Node, child: TextRangeWithKind, _childStartLine: number, sourceFile: SourceFileLike): boolean {
347-
if (isJsxElement(parent) && isParenthesizedExpression(parent.parent)) {
348-
const siblings = parent.getChildren(sourceFile);
349-
const currentNode = find(siblings, arg => arg.pos === child.pos);
350-
if (!currentNode) return false;
351-
352-
const currentIndex = siblings.indexOf(currentNode);
353-
if (currentIndex === 0) return false;
354-
355-
const previousNode = siblings[currentIndex - 1];
356-
const startLineOfPreviousNode = getLineAndCharacterOfPosition(sourceFile, previousNode.getStart()).line;
357-
const endLineOfPreviousNode = getLineAndCharacterOfPosition(sourceFile, previousNode.getEnd()).line;
358-
359-
return startLineOfPreviousNode !== endLineOfPreviousNode;
360-
}
361-
return false;
362-
}
363-
364346
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
365347
return node.parent && getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent, sourceFile);
366348
}
@@ -617,7 +599,7 @@ namespace ts.formatting {
617599
* True when the parent node should indent the given child by an explicit rule.
618600
* @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child.
619601
*/
620-
export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean {
602+
export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: TextRangeWithKind, sourceFile?: SourceFileLike, isNextChild = false): boolean {
621603
return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false)
622604
&& !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent));
623605
}

0 commit comments

Comments
 (0)