Skip to content

fix 'findPrecedingToken' for jsxText #4596

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

Merged
merged 1 commit into from
Sep 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ namespace ts {
return find(startNode || sourceFile);

function findRightmostToken(n: Node): Node {
if (isToken(n)) {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
return n;
}

Expand All @@ -371,24 +371,35 @@ namespace ts {
}

function find(n: Node): Node {
if (isToken(n)) {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
return n;
}

let children = n.getChildren();
const children = n.getChildren();
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i];
if (nodeHasTokens(child)) {
if (position <= child.end) {
if (child.getStart(sourceFile) >= position) {
// actual start of the node is past the position - previous token should be at the end of previous child
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate)
}
else {
// candidate should be in this node
return find(child);
}
// condition 'position < child.end' checks if child node end after the position
// in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc'
// aaaa___bbbb___$__ccc
// after we found child node with end after the position we check if start of the node is after the position.
// if yes - then position is in the trivia and we need to look into the previous child to find the token in question.
// if no - position is in the node itself so we should recurse in it.
// NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia).
// if this is the case - then we should assume that token in question is located in previous child.
if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) {
const start = child.getStart(sourceFile);
const lookInPreviousChild =
(start >= position) || // cursor in the leading trivia
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText

if (lookInPreviousChild) {
// actual start of the node is past the position - previous token should be at the end of previous child
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate)
}
else {
// candidate should be in this node
return find(child);
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions tests/cases/fourslash/indentationInJsx1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />

//@Filename: file.tsx
////(function () {
//// return (
//// <div>
//// <div>
//// </div>
//// /*indent2*/
//// </div>
//// )
////})


format.document();
goTo.marker("indent2");
verify.indentationIs(12);
7 changes: 7 additions & 0 deletions tests/cases/fourslash/indentationInJsx2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// <reference path="fourslash.ts"/>

//@Filename: file.tsx
////<div>/*1*/
goTo.marker("1");
edit.insert("\n");
verify.indentationIs(0);