Skip to content

Commit b65e5b4

Browse files
committed
Fix Jsx formatting error and added tests
1 parent 4c43e09 commit b65e5b4

File tree

5 files changed

+97
-21
lines changed

5 files changed

+97
-21
lines changed

src/compiler/scanner.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,12 +2273,6 @@ namespace ts {
22732273

22742274
while (pos < end) {
22752275

2276-
// We want to keep track of the last non-whitespace (but including
2277-
// newlines character for hitting the end of the JSX Text region)
2278-
if (!isWhiteSpaceSingleLine(char)) {
2279-
lastNonWhitespace = pos;
2280-
}
2281-
22822276
char = text.charCodeAt(pos);
22832277
if (char === CharacterCodes.openBrace) {
22842278
break;
@@ -2297,7 +2291,8 @@ namespace ts {
22972291
error(Diagnostics.Unexpected_token_Did_you_mean_or_rbrace, pos, 1);
22982292
}
22992293

2300-
if (lastNonWhitespace > 0) lastNonWhitespace++;
2294+
// We want to track the last character that is not whitespace to mark the end position of the token.
2295+
if (!isWhiteSpaceLike(char)) lastNonWhitespace = pos;
23012296

23022297
// FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces.
23032298
// i.e (- : whitespace)
@@ -2315,8 +2310,9 @@ namespace ts {
23152310
pos++;
23162311
}
23172312

2318-
const endPosition = lastNonWhitespace === -1 ? pos : lastNonWhitespace;
2319-
tokenValue = text.substring(startPos, endPosition);
2313+
if(lastNonWhitespace !== -1) pos = lastNonWhitespace + 1;
2314+
2315+
tokenValue = text.substring(startPos, pos);
23202316

23212317
return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText;
23222318
}

src/services/formatting/formatting.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -759,15 +759,22 @@ namespace ts.formatting {
759759
if (child.kind === SyntaxKind.JsxText) {
760760
const range: TextRange = { pos: child.getStart(), end: child.getEnd() };
761761
if (range.pos !== range.end) { // don't indent zero-width jsx text
762-
const siblings = parent.getChildren(sourceFile);
763-
const currentIndex = findIndex(siblings, arg => arg.pos === child.pos);
764-
const previousNode = siblings[currentIndex - 1];
762+
let tempNode: Node
763+
let previousNode: Node | undefined;
764+
forEachChild(parent, childNode => {
765+
if (childNode.pos === child.pos) {
766+
previousNode = tempNode;
767+
return true;
768+
}
769+
tempNode = childNode;
770+
});
771+
765772
if (previousNode) {
766773
// The jsx text needs no indentation whatsoever if it ends on the same line the previous sibling ends on
767774
if (sourceFile.getLineAndCharacterOfPosition(range.end).line !== sourceFile.getLineAndCharacterOfPosition(previousNode.end).line) {
768775
// The first line is (already) "indented" if the text starts on the same line as the previous sibling element ends on
769776
const firstLineIsIndented = sourceFile.getLineAndCharacterOfPosition(range.pos).line === sourceFile.getLineAndCharacterOfPosition(previousNode.end).line;
770-
indentMultilineCommentOrJsxText(range, childIndentation.indentation, firstLineIsIndented, /*indentFinalLine*/ false, /*jsxStyle*/ true);
777+
indentMultilineCommentOrJsxText(range, childIndentation.indentation, firstLineIsIndented, /*indentFinalLine*/ true, /*jsxStyle*/ true);
771778
}
772779
}
773780
}

src/services/formatting/formattingScanner.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,7 @@ namespace ts.formatting {
124124
}
125125

126126
function shouldRescanJsxText(node: Node): boolean {
127-
const isJSXText = isJsxText(node);
128-
if (isJSXText) {
129-
const containingElement = findAncestor(node.parent, p => isJsxElement(p));
130-
if (!containingElement) return false; // should never happen
131-
return !isParenthesizedExpression(containingElement.parent);
132-
}
133-
return false;
127+
return isJsxText(node);
134128
}
135129

136130
function shouldRescanSlashToken(container: Node): boolean {
@@ -160,7 +154,7 @@ namespace ts.formatting {
160154
shouldRescanTemplateToken(n) ? ScanAction.RescanTemplateToken :
161155
shouldRescanJsxIdentifier(n) ? ScanAction.RescanJsxIdentifier :
162156
shouldRescanJsxText(n) ? ScanAction.RescanJsxText :
163-
shouldRescanJsxAttributeValue(n) ? ScanAction.RescanJsxAttributeValue :
157+
shouldRescanJsxAttributeValue(n) ? ScanAction.RescanJsxAttributeValue :
164158
ScanAction.Scan;
165159

166160
if (lastTokenInfo && expectedScanAction === lastScanAction) {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: file.tsx
4+
//// const a = (
5+
//// <div>
6+
//// foo
7+
//// </div>
8+
//// );
9+
////
10+
//// const b = (
11+
//// <div>
12+
//// { foo }
13+
//// </div>
14+
//// );
15+
////
16+
//// const c = (
17+
//// <div>
18+
//// foo
19+
//// { foobar }
20+
//// bar
21+
//// </div>
22+
//// );
23+
////
24+
//// const d =
25+
//// <div>
26+
//// foo
27+
//// </div>;
28+
////
29+
//// const e =
30+
//// <div>
31+
//// { foo }
32+
//// </div>
33+
////
34+
//// const f =
35+
//// <div>
36+
//// foo
37+
//// { foobar }
38+
//// bar
39+
//// </div>
40+
41+
format.document();
42+
43+
verify.currentFileContentIs(
44+
`const a = (
45+
<div>
46+
foo
47+
</div>
48+
);
49+
50+
const b = (
51+
<div>
52+
{foo}
53+
</div>
54+
);
55+
56+
const c = (
57+
<div>
58+
foo
59+
{foobar}
60+
bar
61+
</div>
62+
);
63+
64+
const d =
65+
<div>
66+
foo
67+
</div>;
68+
69+
const e =
70+
<div>
71+
{foo}
72+
</div>
73+
74+
const f =
75+
<div>
76+
foo
77+
{foobar}
78+
bar
79+
</div>`);

0 commit comments

Comments
 (0)