Moved createParentNavigator and createNodeStack to core

This commit is contained in:
Ron Buckton 2015-09-04 10:49:45 -07:00
parent 49a3a3f5b2
commit 923ec29eb9
2 changed files with 243 additions and 243 deletions

View File

@ -791,6 +791,249 @@ namespace ts {
getSignatureConstructor: () => <any>Signature
};
/**
* Creates an object used to navigate the ancestor's of a node by following parent pointers.
* @param currentNode The current node for the navigator.
*/
export function createParentNavigator(currentNode: Node): ParentNavigator {
/** Traverses the parent pointers for the current node to find the root node. */
function getRoot() {
let rootNode = currentNode;
while (rootNode && rootNode.parent) {
rootNode = rootNode.parent;
}
return rootNode;
}
/** Gets the grandparent of the current node, without moving the navigator. */
function getGrandparent() {
let parent = getParent();
return parent ? parent.parent : undefined;
}
/** Gets the parent of the current node, without moving the navigator. */
function getParent() {
return currentNode ? currentNode.parent : undefined;
}
/** Gets the current node. */
function getNode() {
return currentNode;
}
/** Gets the SyntaxKind for the current node. */
function getKind() {
return currentNode ? currentNode.kind : undefined;
}
/** Navigates to the parent of the current node if it has one. */
function moveToParent(): boolean {
let parent = getParent();
if (parent) {
currentNode = parent;
return true;
}
return false;
}
/** Navigates to the root node for the current node. */
function moveToRoot(): boolean {
let rootNode = getRoot();
if (rootNode) {
currentNode = rootNode;
return true;
}
return false;
}
/** Creates a new ParentNavigator from the current node. */
function createParentNavigator() {
return ts.createParentNavigator(currentNode);
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToParent,
moveToRoot,
createParentNavigator,
};
}
/**
* Creates a node stack used to maintain parent relationships without parent pointers.
*/
export function createNodeStack(): NodeStack {
let stackSize: number = 0;
let stack: Node[] = [];
let rootNode: Node;
let parentNode: Node;
let currentNode: Node;
/** Gets the node at the bottom of the stack. */
function getRoot() {
return rootNode;
}
/** Gets the node two steps back from the top of the stack. */
function getGrandparent() {
return peekNode(2);
}
/** Gets the node one step back from the top of the stack. */
function getParent() {
return parentNode;
}
/** Gets the node at the top of the stack. */
function getNode() {
return currentNode;
}
/** Gets the SyntaxKind for the node at the top of the stack. */
function getKind() {
return currentNode ? currentNode.kind : undefined;
}
/** Pushes a node onto the stack. */
function pushNode(node: Node): void {
stackSize++;
if (stackSize > 2) {
stack.push(parentNode);
}
else if (stackSize === 1) {
rootNode = node;
}
parentNode = currentNode;
currentNode = node;
}
/** Pops the top node from the stack. */
function popNode(): void {
currentNode = parentNode;
parentNode = stackSize > 2 ? stack.pop() : undefined;
stackSize--;
if (stackSize === 0) {
rootNode = undefined;
}
}
/** Replaces the node at the top of the stack. */
function setNode(node: Node): void {
currentNode = node;
}
/** Peeks at a node a specified number of steps back from the top of the stack. */
function peekNode(stackOffset: number): Node {
switch (stackOffset) {
case 0: return currentNode;
case 1: return parentNode;
default: return stackSize > 2 ? stack[stackSize - 1 - stackOffset] : undefined;
}
}
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
function findAncestorNode<T extends Node>(match: (node: Node) => node is T): T;
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
function findAncestorNode(match: (node: Node) => boolean): Node;
function findAncestorNode(match: (node: Node) => boolean) {
if (parentNode && match(parentNode)) {
return parentNode;
}
for (let i = stack.length; i >= 0; i--) {
let node = stack[i];
if (match(node)) {
return node;
}
}
return undefined;
}
/** Creates a parent navigator from the top of the stack. */
function createParentNavigator() {
return createParentNavigatorFromStackOffset(0);
}
/** Creates a parent navigator a specified number of steps back from the top of the stack. */
function createParentNavigatorFromStackOffset(stackOffset: number): ParentNavigator {
/** Gets the node two steps back from the current stack offset. */
function getGrandparent() {
return peekNode(stackOffset + 2);
}
/** Gets the node one step back from the current stack offset. */
function getParent() {
return peekNode(stackOffset + 1);
}
/** Gets the node at the current stack offset. */
function getNode() {
return peekNode(stackOffset);
}
/** Gets the SyntaxKind of the node at the current stack offset. */
function getKind() {
let node = getNode();
return node ? node.kind : undefined;
}
/** Navigates to the node one step back from the current stack offset. */
function moveToParent() {
if (getParent()) {
stackOffset++;
return true;
}
return false;
}
/** Navigates to the node at the bottom of the stack. */
function moveToRoot() {
if (stackSize > 0) {
stackOffset = stackSize;
return true;
}
return false;
}
/** Creates a new ParentNavigator from the current stack offset. */
function createParentNavigator() {
return createParentNavigatorFromStackOffset(stackOffset);
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToRoot,
moveToParent,
createParentNavigator,
};
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
pushNode,
popNode,
setNode,
findAncestorNode,
createParentNavigator,
};
}
export const enum AssertionLevel {
None = 0,
Normal = 1,

View File

@ -243,249 +243,6 @@ namespace ts {
return getBaseFileName(moduleName).replace(/^(\d)/, "_$1").replace(/\W/g, "_");
}
/**
* Creates an object used to navigate the ancestor's of a node by following parent pointers.
* @param currentNode The current node for the navigator.
*/
export function createParentNavigator(currentNode: Node): ParentNavigator {
/** Traverses the parent pointers for the current node to find the root node. */
function getRoot() {
let rootNode = currentNode;
while (rootNode && rootNode.parent) {
rootNode = rootNode.parent;
}
return rootNode;
}
/** Gets the grandparent of the current node, without moving the navigator. */
function getGrandparent() {
let parent = getParent();
return parent ? parent.parent : undefined;
}
/** Gets the parent of the current node, without moving the navigator. */
function getParent() {
return currentNode ? currentNode.parent : undefined;
}
/** Gets the current node. */
function getNode() {
return currentNode;
}
/** Gets the SyntaxKind for the current node. */
function getKind() {
return currentNode ? currentNode.kind : undefined;
}
/** Navigates to the parent of the current node if it has one. */
function moveToParent(): boolean {
let parent = getParent();
if (parent) {
currentNode = parent;
return true;
}
return false;
}
/** Navigates to the root node for the current node. */
function moveToRoot(): boolean {
let rootNode = getRoot();
if (rootNode) {
currentNode = rootNode;
return true;
}
return false;
}
/** Creates a new ParentNavigator from the current node. */
function createParentNavigator() {
return ts.createParentNavigator(currentNode);
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToParent,
moveToRoot,
createParentNavigator,
};
}
/**
* Creates a node stack used to maintain parent relationships without parent pointers.
*/
export function createNodeStack(): NodeStack {
let stackSize: number = 0;
let stack: Node[] = [];
let rootNode: Node;
let parentNode: Node;
let currentNode: Node;
/** Gets the node at the bottom of the stack. */
function getRoot() {
return rootNode;
}
/** Gets the node two steps back from the top of the stack. */
function getGrandparent() {
return peekNode(2);
}
/** Gets the node one step back from the top of the stack. */
function getParent() {
return parentNode;
}
/** Gets the node at the top of the stack. */
function getNode() {
return currentNode;
}
/** Gets the SyntaxKind for the node at the top of the stack. */
function getKind() {
return currentNode ? currentNode.kind : undefined;
}
/** Pushes a node onto the stack. */
function pushNode(node: Node): void {
stackSize++;
if (stackSize > 2) {
stack.push(parentNode);
}
else if (stackSize === 1) {
rootNode = node;
}
parentNode = currentNode;
currentNode = node;
}
/** Pops the top node from the stack. */
function popNode(): void {
currentNode = parentNode;
parentNode = stackSize > 2 ? stack.pop() : undefined;
stackSize--;
if (stackSize === 0) {
rootNode = undefined;
}
}
/** Replaces the node at the top of the stack. */
function setNode(node: Node): void {
currentNode = node;
}
/** Peeks at a node a specified number of steps back from the top of the stack. */
function peekNode(stackOffset: number): Node {
switch (stackOffset) {
case 0: return currentNode;
case 1: return parentNode;
default: return stackSize > 2 ? stack[stackSize - 1 - stackOffset] : undefined;
}
}
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
function findAncestorNode<T extends Node>(match: (node: Node) => node is T): T;
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
function findAncestorNode(match: (node: Node) => boolean): Node;
function findAncestorNode(match: (node: Node) => boolean) {
if (parentNode && match(parentNode)) {
return parentNode;
}
for (let i = stack.length; i >= 0; i--) {
let node = stack[i];
if (match(node)) {
return node;
}
}
return undefined;
}
/** Creates a parent navigator from the top of the stack. */
function createParentNavigator() {
return createParentNavigatorFromStackOffset(0);
}
/** Creates a parent navigator a specified number of steps back from the top of the stack. */
function createParentNavigatorFromStackOffset(stackOffset: number): ParentNavigator {
/** Gets the node two steps back from the current stack offset. */
function getGrandparent() {
return peekNode(stackOffset + 2);
}
/** Gets the node one step back from the current stack offset. */
function getParent() {
return peekNode(stackOffset + 1);
}
/** Gets the node at the current stack offset. */
function getNode() {
return peekNode(stackOffset);
}
/** Gets the SyntaxKind of the node at the current stack offset. */
function getKind() {
let node = getNode();
return node ? node.kind : undefined;
}
/** Navigates to the node one step back from the current stack offset. */
function moveToParent() {
if (getParent()) {
stackOffset++;
return true;
}
return false;
}
/** Navigates to the node at the bottom of the stack. */
function moveToRoot() {
if (stackSize > 0) {
stackOffset = stackSize;
return true;
}
return false;
}
/** Creates a new ParentNavigator from the current stack offset. */
function createParentNavigator() {
return createParentNavigatorFromStackOffset(stackOffset);
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToRoot,
moveToParent,
createParentNavigator,
};
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
pushNode,
popNode,
setNode,
findAncestorNode,
createParentNavigator,
};
}
export function isBlockOrCatchScoped(declaration: Declaration) {
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
isCatchClauseVariableDeclaration(declaration);