ソースを参照

Refactoring of NodeUtils and NodeGuards classes

sanex3339 7 年 前
コミット
21641cd0dd

ファイルの差分が大きいため隠しています
+ 0 - 0
dist/index.js


+ 2 - 7
src/node/NodeGuards.ts

@@ -191,15 +191,10 @@ export class NodeGuards {
 
 
     /**
     /**
      * @param {Node} node
      * @param {Node} node
+     * @param {Node} parentNode
      * @returns {boolean}
      * @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) || (
         return NodeGuards.isProgramNode(node) || (
             NodeGuards.isBlockStatementNode(node)
             NodeGuards.isBlockStatementNode(node)
             && NodeGuards.nodesWithBlockScope.includes(parentNode.type)
             && NodeGuards.nodesWithBlockScope.includes(parentNode.type)

+ 80 - 61
src/node/NodeUtils.ts

@@ -35,45 +35,7 @@ export class NodeUtils {
      * @returns {T}
      * @returns {T}
      */
      */
     public static clone <T extends ESTree.Node = ESTree.Node> (astTree: T): 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[]}
      * @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;
         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;
+    }
 }
 }

+ 5 - 21
test/unit-tests/node/node-guards/NodeGuards.spec.ts

@@ -22,7 +22,7 @@ describe('NodeGuards', () => {
 
 
                 before(() => {
                 before(() => {
                     NodeUtils.parentize(parentNode);
                     NodeUtils.parentize(parentNode);
-                    result = NodeGuards.isNodeHasBlockScope(node);
+                    result = NodeGuards.isNodeHasBlockScope(node, parentNode);
                 });
                 });
 
 
                 it('should check if node has block scope', () => {
                 it('should check if node has block scope', () => {
@@ -42,7 +42,7 @@ describe('NodeGuards', () => {
 
 
                 before(() => {
                 before(() => {
                     NodeUtils.parentize(parentNode);
                     NodeUtils.parentize(parentNode);
-                    result = NodeGuards.isNodeHasBlockScope(node);
+                    result = NodeGuards.isNodeHasBlockScope(node, parentNode);
                 });
                 });
 
 
                 it('should check if node has block scope', () => {
                 it('should check if node has block scope', () => {
@@ -80,7 +80,7 @@ describe('NodeGuards', () => {
 
 
                 before(() => {
                 before(() => {
                     NodeUtils.parentize(parentNode);
                     NodeUtils.parentize(parentNode);
-                    result = NodeGuards.isNodeHasBlockScope(node);
+                    result = NodeGuards.isNodeHasBlockScope(node, parentNode);
                 });
                 });
 
 
                 it('should check if node has block scope', () => {
                 it('should check if node has block scope', () => {
@@ -108,7 +108,7 @@ describe('NodeGuards', () => {
 
 
                 before(() => {
                 before(() => {
                     NodeUtils.parentize(parentNode);
                     NodeUtils.parentize(parentNode);
-                    result = NodeGuards.isNodeHasBlockScope(node);
+                    result = NodeGuards.isNodeHasBlockScope(node, parentNode);
                 });
                 });
 
 
                 it('should check if node has block scope', () => {
                 it('should check if node has block scope', () => {
@@ -128,7 +128,7 @@ describe('NodeGuards', () => {
 
 
                 before(() => {
                 before(() => {
                     NodeUtils.parentize(parentNode);
                     NodeUtils.parentize(parentNode);
-                    result = NodeGuards.isNodeHasBlockScope(node);
+                    result = NodeGuards.isNodeHasBlockScope(node, parentNode);
                 });
                 });
 
 
                 it('should check if node has block scope', () => {
                 it('should check if node has block scope', () => {
@@ -136,22 +136,6 @@ describe('NodeGuards', () => {
                 });
                 });
             });
             });
         });
         });
-
-        describe('exception checks', () => {
-            describe('no `parentNode` property', () => {
-                const node: ESTree.Node = Nodes.getBlockStatementNode();
-
-                let testFunc: Function;
-
-                before(() => {
-                    testFunc = () => NodeGuards.isNodeHasBlockScope(node);
-                });
-
-                it('should check if node has block scope', () => {
-                    assert.throw(testFunc, Error);
-                });
-            });
-        });
     });
     });
 
 
     describe('isNodeHasScope (node: ESTree.Node): node is TNodeWithScope', () => {
     describe('isNodeHasScope (node: ESTree.Node): node is TNodeWithScope', () => {

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません