Added more tests. Updated NodeAppender class to work with all scope nodes.

This commit is contained in:
sanex3339
2018-01-04 23:02:15 +03:00
parent 273f0b331a
commit 3e1e1142ba
11 changed files with 624 additions and 77 deletions
@@ -18,9 +18,9 @@ import { NodeUtils } from '../../node/NodeUtils';
@injectable()
export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
/**
* @type {Map<VariableDeclarator, BlockStatement>}
* @type {Map<VariableDeclarator, TNodeWithScope>}
*/
private cachedScopeNodesMap: Map <ESTree.VariableDeclarator, ESTree.BlockStatement> = new Map();
private cachedScopeNodesMap: Map <ESTree.VariableDeclarator, TNodeWithScope> = new Map();
/**
* @param {IRandomGenerator} randomGenerator
@@ -34,27 +34,22 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
}
/**
* @param {BlockStatement} scopeNode
* @param {TNodeWithScope} scopeNode
* @param {ExpressionStatement[]} expressionStatements
* @param {Node} variableDeclarator
*/
private static appendExpressionStatements (
scopeNode: ESTree.BlockStatement,
scopeNode: TNodeWithScope,
expressionStatements: ESTree.ExpressionStatement[],
variableDeclarator: ESTree.Node
): void {
const variableDeclaration: ESTree.Node | undefined = variableDeclarator.parentNode;
if (
!variableDeclaration
|| !NodeGuards.isVariableDeclarationNode(variableDeclaration)
) {
if (!variableDeclaration || !NodeGuards.isVariableDeclarationNode(variableDeclaration)) {
throw new Error('Cannot find variable declaration for variable declarator');
}
const indexInBlockStatement: number = scopeNode.body.indexOf(variableDeclaration);
NodeAppender.insertNodeAtIndex(scopeNode, expressionStatements, indexInBlockStatement + 1);
NodeAppender.insertNodeAfter(scopeNode, expressionStatements, variableDeclaration);
}
/**
@@ -108,7 +103,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
const scopeNode: TNodeWithScope | null = NodeUtils.getScopeOfNode(variableDeclarator);
if (!scopeNode || !NodeGuards.isBlockStatementNode(scopeNode)) {
if (!scopeNode || !NodeGuards.isNodeHasScope(scopeNode)) {
return objectExpressionNode;
}
@@ -216,7 +211,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
return objectExpressionNode;
}
const scopeNode: ESTree.BlockStatement | undefined = this.cachedScopeNodesMap.get(variableDeclarator);
const scopeNode: TNodeWithScope | undefined = this.cachedScopeNodesMap.get(variableDeclarator);
if (!scopeNode) {
return objectExpressionNode;
+80 -54
View File
@@ -4,6 +4,8 @@ import { TNodeWithBlockScope } from '../types/node/TNodeWithBlockScope';
import { TStatement } from '../types/node/TStatement';
import { IStackTraceData } from '../interfaces/analyzers/stack-trace-analyzer/IStackTraceData';
import { TNodeWithScope } from '../types/node/TNodeWithScope';
import { NodeGuards } from './NodeGuards';
/**
* This class appends node into a first deepest BlockStatement in order of function calls
@@ -24,23 +26,20 @@ import { IStackTraceData } from '../interfaces/analyzers/stack-trace-analyzer/IS
*/
export class NodeAppender {
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {TStatement[]} nodeBodyStatements
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} scopeStatements
*/
public static appendNode (
blockScopeNode: TNodeWithBlockScope,
nodeBodyStatements: TStatement[]
): void {
if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
nodeBodyStatements = [];
public static appendNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void {
if (!NodeAppender.validateScopeStatements(scopeStatements)) {
scopeStatements = [];
}
nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
blockScopeNode.body = [
...blockScopeNode.body,
...nodeBodyStatements
];
NodeAppender.setScopeNodeStatements(scopeNode, [
...NodeAppender.getScopeNodeStatements(scopeNode),
...scopeStatements
]);
}
/**
@@ -96,70 +95,97 @@ export class NodeAppender {
}
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {TStatement[]} nodeBodyStatements
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} scopeStatements
* @param {Node} targetStatement
*/
public static insertNodeAfter (scopeNode: TNodeWithScope, scopeStatements: TStatement[], targetStatement: ESTree.Statement): void {
const indexInScopeStatement: number = NodeAppender
.getScopeNodeStatements(scopeNode)
.indexOf(targetStatement);
NodeAppender.insertNodeAtIndex(scopeNode, scopeStatements, indexInScopeStatement + 1);
}
/**
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} scopeStatements
* @param {number} index
*/
public static insertNodeAtIndex (
blockScopeNode: TNodeWithBlockScope,
nodeBodyStatements: TStatement[],
index: number
): void {
if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
nodeBodyStatements = [];
public static insertNodeAtIndex (scopeNode: TNodeWithScope, scopeStatements: TStatement[], index: number): void {
if (!NodeAppender.validateScopeStatements(scopeStatements)) {
scopeStatements = [];
}
nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
blockScopeNode.body = [
...blockScopeNode.body.slice(0, index),
...nodeBodyStatements,
...blockScopeNode.body.slice(index)
];
NodeAppender.setScopeNodeStatements(scopeNode, [
...NodeAppender.getScopeNodeStatements(scopeNode).slice(0, index),
...scopeStatements,
...NodeAppender.getScopeNodeStatements(scopeNode).slice(index)
]);
}
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {TStatement[]} nodeBodyStatements
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} scopeStatements
*/
public static prependNode (
blockScopeNode: TNodeWithBlockScope,
nodeBodyStatements: TStatement[]
): void {
if (!NodeAppender.validateBodyStatements(nodeBodyStatements)) {
nodeBodyStatements = [];
public static prependNode (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): void {
if (!NodeAppender.validateScopeStatements(scopeStatements)) {
scopeStatements = [];
}
nodeBodyStatements = NodeAppender.parentizeBodyStatementsBeforeAppend(blockScopeNode, nodeBodyStatements);
scopeStatements = NodeAppender.parentizeScopeStatementsBeforeAppend(scopeNode, scopeStatements);
blockScopeNode.body = [
...nodeBodyStatements,
...blockScopeNode.body,
];
NodeAppender.setScopeNodeStatements(scopeNode, [
...scopeStatements,
...NodeAppender.getScopeNodeStatements(scopeNode),
]);
}
/**
* @param {TNodeWithBlockScope} blockScopeNode
* @param {TStatement[]} nodeBodyStatements
* @param {TNodeWithScope} scopeNode
* @returns {TStatement[]}
*/
private static parentizeBodyStatementsBeforeAppend (
blockScopeNode: TNodeWithBlockScope,
nodeBodyStatements: TStatement[]
): TStatement[] {
nodeBodyStatements.forEach((statement: TStatement) => {
statement.parentNode = blockScopeNode;
});
private static getScopeNodeStatements (scopeNode: TNodeWithScope): TStatement[] {
if (NodeGuards.isSwitchCaseNode(scopeNode)) {
return scopeNode.consequent;
}
return nodeBodyStatements;
return scopeNode.body;
}
/**
* @param {TStatement[]} nodeBodyStatements
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} scopeStatements
* @returns {TStatement[]}
*/
private static parentizeScopeStatementsBeforeAppend (scopeNode: TNodeWithScope, scopeStatements: TStatement[]): TStatement[] {
scopeStatements.forEach((statement: TStatement) => {
statement.parentNode = scopeNode;
});
return scopeStatements;
}
/**
* @param {TNodeWithScope} scopeNode
* @param {TStatement[]} statements
*/
private static setScopeNodeStatements (scopeNode: TNodeWithScope, statements: TStatement[]): void {
if (NodeGuards.isSwitchCaseNode(scopeNode)) {
scopeNode.consequent = <ESTree.Statement[]>statements;
} else {
scopeNode.body = statements;
}
}
/**
* @param {TStatement[]} scopeStatement
* @returns {boolean}
*/
private static validateBodyStatements (nodeBodyStatements: TStatement[]): boolean {
return nodeBodyStatements.every((statementNode: TStatement) => {
private static validateScopeStatements (scopeStatement: TStatement[]): boolean {
return scopeStatement.every((statementNode: TStatement) => {
return !!statementNode && statementNode.hasOwnProperty('type');
});
}
+2 -2
View File
@@ -197,7 +197,7 @@ export class NodeGuards {
const parentNode: ESTree.Node | undefined = node.parentNode;
if (!parentNode) {
return false;
throw new ReferenceError('`parentNode` property of given node is `undefined`');
}
return NodeGuards.isProgramNode(node) || (
@@ -271,7 +271,7 @@ export class NodeGuards {
parentNode.key === node;
const parentNodeIsMemberExpressionNode: boolean = (
NodeGuards.isMemberExpressionNode(parentNode) &&
parentNode.computed === false &&
!parentNode.computed &&
parentNode.property === node
);
const parentNodeIsMethodDefinitionNode: boolean = NodeGuards.isMethodDefinitionNode(parentNode) &&
+24
View File
@@ -305,6 +305,30 @@ export class Nodes {
};
}
/**
* @param {Expression} key
* @param {FunctionExpression} value
* @param {"constructor" | "method" | "get" | "set"} kind
* @param {boolean} computed
* @returns {MethodDefinition}
*/
public static getMethodDefinitionNode (
key: ESTree.Expression,
value: ESTree.FunctionExpression,
kind: 'constructor' | 'method' | 'get' | 'set',
computed: boolean,
): ESTree.MethodDefinition {
return {
type: NodeType.MethodDefinition,
key,
value,
kind,
computed,
static: false,
obfuscatedNode: false
};
}
/**
* @param {Property[]} properties
* @returns {ObjectExpression}