-
Notifications
You must be signed in to change notification settings - Fork 3
Offload all jsx text indentation handling to indentMultilineCommentOrJsxText #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -501,9 +501,6 @@ namespace ts.formatting { | |
else if (SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile)) { | ||
return { indentation: parentDynamicIndentation.getIndentation(), delta }; | ||
} | ||
else if (SmartIndenter.isJSXClosingWithMultiLineText(parent, node, startLine, sourceFile)) { | ||
return { indentation: parentDynamicIndentation.getIndentation(), delta }; | ||
} | ||
else { | ||
return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta }; | ||
} | ||
|
@@ -652,6 +649,11 @@ namespace ts.formatting { | |
if (tokenInfo.token.end > node.end) { | ||
break; | ||
} | ||
if (node.kind === SyntaxKind.JsxText) { | ||
// Intentation rules for jsx text are handled by `indentMultilineCommentOrJsxText` inside `processChildNode`; just fastforward past it here | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notably, the formatting scanner actually doesn't handle scanning JSX correctly, like, at all; so the only thing that even makes sense is to fastforward over it - otherwise we do silly things like interpret words within the jsxtext as identifiers. |
||
formattingScanner.advance(); | ||
continue; | ||
} | ||
consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node); | ||
} | ||
|
||
|
@@ -741,7 +743,20 @@ namespace ts.formatting { | |
processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); | ||
if (child.kind === SyntaxKind.JsxText) { | ||
const range: TextRange = { pos: child.getStart(), end: child.getEnd() }; | ||
indentMultilineCommentOrJsxText(range, childIndentation.indentation, /*firstLineIsIndented*/ true, /*indentFinalLine*/ false); | ||
if (range.pos !== range.end) { // don't indent zero-width jsx text | ||
const siblings = parent.getChildren(sourceFile); | ||
const currentNode = find(siblings, arg => arg.pos === child.pos); | ||
const currentIndex = siblings.indexOf(currentNode!); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
const previousNode = siblings[currentIndex - 1]; | ||
if (previousNode) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm... unclear on why this can happen, but |
||
// The jsx text needs no indentation whatsoever if it ends on the same line the previous sibling ends on | ||
if (sourceFile.getLineAndCharacterOfPosition(range.end).line !== sourceFile.getLineAndCharacterOfPosition(previousNode.end).line) { | ||
// The first line is (already) "indented" if the text starts on the same line as the previous sibling element ends on | ||
const firstLineIsIndented = sourceFile.getLineAndCharacterOfPosition(range.pos).line === sourceFile.getLineAndCharacterOfPosition(previousNode.end).line; | ||
indentMultilineCommentOrJsxText(range, childIndentation.indentation, firstLineIsIndented, /*indentFinalLine*/ false, /*jsxStyle*/ true); | ||
} | ||
} | ||
} | ||
} | ||
|
||
childContextNode = node; | ||
|
@@ -1041,7 +1056,7 @@ namespace ts.formatting { | |
return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); | ||
} | ||
|
||
function indentMultilineCommentOrJsxText(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true) { | ||
function indentMultilineCommentOrJsxText(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true, jsxTextStyleIndent?: boolean) { | ||
// split comment in lines | ||
let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; | ||
const endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; | ||
|
@@ -1072,7 +1087,7 @@ namespace ts.formatting { | |
const nonWhitespaceColumnInFirstPart = | ||
SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); | ||
|
||
if (indentation === nonWhitespaceColumnInFirstPart.column) { | ||
if (indentation === nonWhitespaceColumnInFirstPart.column && !jsxTextStyleIndent) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do note - if we choose to remove this line because we prefer the whitespace-preserving style, then we can revert this line, too. |
||
return; | ||
} | ||
|
||
|
@@ -1083,14 +1098,19 @@ namespace ts.formatting { | |
} | ||
|
||
// shift all parts on the delta size | ||
const delta = indentation - nonWhitespaceColumnInFirstPart.column; | ||
let delta = indentation - nonWhitespaceColumnInFirstPart.column; | ||
for (let i = startIndex; i < parts.length; i++ , startLine++) { | ||
const startLinePos = getStartPositionOfLine(startLine, sourceFile); | ||
const nonWhitespaceCharacterAndColumn = | ||
i === 0 | ||
? nonWhitespaceColumnInFirstPart | ||
: SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); | ||
|
||
if (jsxTextStyleIndent) { | ||
// skip adding indentation to blank lines | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So for comments we actually add trailing whitespace, apparently. This seems silly, and causes some jsx text formatting baselines to fail, so we choose not to emit any whitespace on empty lines here to avoid emitting that trailing whitespace. |
||
if (isLineBreak(sourceFile.text.charCodeAt(getStartPositionOfLine(startLine, sourceFile)))) continue; | ||
// reset delta on every line | ||
delta = indentation - nonWhitespaceCharacterAndColumn.column; | ||
} | ||
const newIndentation = nonWhitespaceCharacterAndColumn.column + delta; | ||
if (newIndentation > 0) { | ||
const indentationString = getIndentationString(newIndentation, options); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -343,24 +343,6 @@ namespace ts.formatting { | |
return false; | ||
} | ||
|
||
export function isJSXClosingWithMultiLineText(parent: Node, child: TextRangeWithKind, _childStartLine: number, sourceFile: SourceFileLike): boolean { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of this logic is just now directly in |
||
if (isJsxElement(parent) && isParenthesizedExpression(parent.parent)) { | ||
const siblings = parent.getChildren(sourceFile); | ||
const currentNode = find(siblings, arg => arg.pos === child.pos); | ||
if (!currentNode) return false; | ||
|
||
const currentIndex = siblings.indexOf(currentNode); | ||
if (currentIndex === 0) return false; | ||
|
||
const previousNode = siblings[currentIndex - 1]; | ||
const startLineOfPreviousNode = getLineAndCharacterOfPosition(sourceFile, previousNode.getStart()).line; | ||
const endLineOfPreviousNode = getLineAndCharacterOfPosition(sourceFile, previousNode.getEnd()).line; | ||
|
||
return startLineOfPreviousNode !== endLineOfPreviousNode; | ||
} | ||
return false; | ||
} | ||
|
||
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined { | ||
return node.parent && getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent, sourceFile); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is where we were trying to compensate for the old bad scanner behavior; we'd essentially dedent (or at least choose not to increase the indent) in this case to try to compensate for the extra whitespace the scanner used to provide.