Clean up findPrecedingToken and avoid returning whitespace-only jsx text token (#21903)

This commit is contained in:
Andy
2018-02-12 14:42:16 -08:00
committed by GitHub
parent d07523e9e5
commit 74f01abfcf
4 changed files with 35 additions and 29 deletions

View File

@@ -5153,6 +5153,7 @@ namespace ts {
/**
* True if node is of some token syntax kind.
* For example, this is true for an IfKeyword but not for an IfStatement.
* Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail.
*/
export function isToken(n: Node): boolean {
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;

View File

@@ -761,23 +761,12 @@ namespace ts {
Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result)));
return result;
function findRightmostToken(n: Node): Node {
if (isToken(n)) {
function find(n: Node): Node | undefined {
if (isNonWhitespaceToken(n)) {
return n;
}
const children = n.getChildren();
const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
return candidate && findRightmostToken(candidate);
}
function find(n: Node): Node {
if (isToken(n)) {
return n;
}
const children = n.getChildren();
const children = n.getChildren(sourceFile);
for (let i = 0; i < children.length; i++) {
const child = children[i];
// Note that the span of a node's tokens is [node.getStart(...), node.end).
@@ -795,7 +784,7 @@ namespace ts {
if (lookInPreviousChild) {
// actual start of the node is past the position - previous token should be at the end of previous child
const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate);
return candidate && findRightmostToken(candidate, sourceFile);
}
else {
// candidate should be in this node
@@ -812,23 +801,37 @@ namespace ts {
// Namely we are skipping the check: 'position < node.end'
if (children.length) {
const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
return candidate && findRightmostToken(candidate);
return candidate && findRightmostToken(candidate, sourceFile);
}
}
}
/**
* Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens.
*/
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
for (let i = exclusiveStartPosition - 1; i >= 0; i--) {
const child = children[i];
function isNonWhitespaceToken(n: Node): boolean {
return isToken(n) && !isWhiteSpaceOnlyJsxText(n);
}
if (isWhiteSpaceOnlyJsxText(child)) {
Debug.assert(i > 0, "`JsxText` tokens should not be the first child of `JsxElement | JsxSelfClosingElement`");
}
else if (nodeHasTokens(children[i])) {
return children[i];
}
function findRightmostToken(n: Node, sourceFile: SourceFile): Node | undefined {
if (isNonWhitespaceToken(n)) {
return n;
}
const children = n.getChildren(sourceFile);
const candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
return candidate && findRightmostToken(candidate, sourceFile);
}
/**
* Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens.
*/
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node | undefined {
for (let i = exclusiveStartPosition - 1; i >= 0; i--) {
const child = children[i];
if (isWhiteSpaceOnlyJsxText(child)) {
Debug.assert(i > 0, "`JsxText` tokens should not be the first child of `JsxElement | JsxSelfClosingElement`");
}
else if (nodeHasTokens(children[i])) {
return children[i];
}
}
}
@@ -893,7 +896,7 @@ namespace ts {
return false;
}
export function isWhiteSpaceOnlyJsxText(node: Node): node is JsxText {
function isWhiteSpaceOnlyJsxText(node: Node): boolean {
return isJsxText(node) && node.containsOnlyWhiteSpaces;
}