Refactoring of NodeUtils and NodeGuards classes

This commit is contained in:
sanex3339
2018-01-05 00:25:44 +03:00
parent 3e1e1142ba
commit 21641cd0dd
4 changed files with 88 additions and 90 deletions
+2 -7
View File
@@ -191,15 +191,10 @@ export class NodeGuards {
/**
* @param {Node} node
* @param {Node} parentNode
* @returns {boolean}
*/
public static isNodeHasBlockScope (node: ESTree.Node): node is TNodeWithBlockScope {
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
public static isNodeHasBlockScope (node: ESTree.Node, parentNode: ESTree.Node): node is TNodeWithBlockScope {
return NodeGuards.isProgramNode(node) || (
NodeGuards.isBlockStatementNode(node)
&& NodeGuards.nodesWithBlockScope.includes(parentNode.type)
+80 -61
View File
@@ -35,45 +35,7 @@ export class NodeUtils {
* @returns {T}
*/
public static clone <T extends ESTree.Node = ESTree.Node> (astTree: T): T {
/**
* @param {T} node
* @returns {T}
*/
const cloneRecursive: (node: T) => T = (node: T) => {
if (node === null) {
return node;
}
const copy: TObject = {};
Object
.keys(node)
.forEach((property: string): void => {
if (property === 'parentNode') {
return;
}
const value: any = (<TObject>node)[property];
let clonedValue: any | null;
if (value === null || value instanceof RegExp) {
clonedValue = value;
} else if (Array.isArray(value)) {
clonedValue = value.map(cloneRecursive);
} else if (typeof value === 'object') {
clonedValue = cloneRecursive(value);
} else {
clonedValue = value;
}
copy[property] = clonedValue;
});
return <T>copy;
};
return NodeUtils.parentize(cloneRecursive(astTree));
return NodeUtils.parentize(NodeUtils.cloneRecursive(astTree));
}
/**
@@ -102,30 +64,11 @@ export class NodeUtils {
}
/**
* @param {NodeGuards} node
* @param {TNodeWithBlockScope[]} blockScopes
* @param {Node} targetNode
* @returns {TNodeWithBlockScope[]}
*/
public static getBlockScopesOfNode (node: ESTree.Node, blockScopes: TNodeWithBlockScope[] = []): TNodeWithBlockScope[] {
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
if (NodeGuards.isBlockStatementNode(parentNode) && NodeGuards.isNodeHasBlockScope(parentNode)) {
blockScopes.push(parentNode);
}
if (node !== parentNode) {
return NodeUtils.getBlockScopesOfNode(parentNode, blockScopes);
}
if (NodeGuards.isNodeHasBlockScope(parentNode)) {
blockScopes.push(parentNode);
}
return blockScopes;
public static getBlockScopesOfNode (targetNode: ESTree.Node): TNodeWithBlockScope[] {
return NodeUtils.getBlockScopesOfNodeRecursive(targetNode);
}
/**
@@ -181,4 +124,80 @@ export class NodeUtils {
return node;
}
/**
* @param {T} node
* @returns {T}
*/
private static cloneRecursive <T> (node: T): T {
if (node === null) {
return node;
}
const copy: TObject = {};
Object
.keys(node)
.forEach((property: string): void => {
if (property === 'parentNode') {
return;
}
const value: any = (<TObject>node)[property];
let clonedValue: any | null;
if (value === null || value instanceof RegExp) {
clonedValue = value;
} else if (Array.isArray(value)) {
clonedValue = value.map(NodeUtils.cloneRecursive);
} else if (typeof value === 'object') {
clonedValue = NodeUtils.cloneRecursive(value);
} else {
clonedValue = value;
}
copy[property] = clonedValue;
});
return <T>copy;
}
/**
* @param {Node} node
* @param {TNodeWithBlockScope[]} blockScopes
* @param {number} depth
* @returns {TNodeWithBlockScope[]}
*/
private static getBlockScopesOfNodeRecursive (
node: ESTree.Node,
blockScopes: TNodeWithBlockScope[] = [],
depth: number = 0
): TNodeWithBlockScope[] {
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
if (
/**
* we can add program node instantly
*/
NodeGuards.isProgramNode(node) ||
/**
* we shouldn't add to the array input node that is node with block scope itself
* so, on depth 0 we will skip push to the array of block scopes
*/
(depth && NodeGuards.isNodeHasBlockScope(node, parentNode))
) {
blockScopes.push(node);
}
if (node !== parentNode) {
return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, blockScopes, ++depth);
}
return blockScopes;
}
}