|
@@ -1,148 +0,0 @@
|
|
-import * as estraverse from 'estraverse';
|
|
|
|
-import * as ESTree from 'estree';
|
|
|
|
-
|
|
|
|
-import { TNodeWithBlockStatement } from './types/TNodeWithBlockStatement';
|
|
|
|
-
|
|
|
|
-import { IStackTraceData } from './interfaces/IStackTraceData';
|
|
|
|
-import { IStackTraceAnalyzer } from './interfaces/IAnalyzer';
|
|
|
|
-
|
|
|
|
-import { Nodes } from './Nodes';
|
|
|
|
-import { NodeUtils } from './NodeUtils';
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This class generates a data with code stack trace functions calls
|
|
|
|
- *
|
|
|
|
- * For example:
|
|
|
|
- *
|
|
|
|
- * function Foo () {
|
|
|
|
- * var baz = function () {
|
|
|
|
- *
|
|
|
|
- * }
|
|
|
|
- *
|
|
|
|
- * baz();
|
|
|
|
- * }
|
|
|
|
- *
|
|
|
|
- * foo();
|
|
|
|
- *
|
|
|
|
- * Will generate a structure like:
|
|
|
|
- *
|
|
|
|
- * [
|
|
|
|
- * {
|
|
|
|
- * callee: FOO_FUNCTION_NODE
|
|
|
|
- * name: 'Foo',
|
|
|
|
- * trace: [
|
|
|
|
- * {
|
|
|
|
- * callee: BAZ_FUNCTION_NODE,
|
|
|
|
- * name: 'baz,
|
|
|
|
- * trace: []
|
|
|
|
- * }
|
|
|
|
- * ]
|
|
|
|
- * }
|
|
|
|
- * ]
|
|
|
|
- */
|
|
|
|
-export class StackTraceAnalyzer implements IStackTraceAnalyzer {
|
|
|
|
- /**
|
|
|
|
- * @type {ESTree.Node[]}
|
|
|
|
- */
|
|
|
|
- private blockScopeBody: ESTree.Node[];
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @type {IStackTraceData[]}
|
|
|
|
- */
|
|
|
|
- private stackTraceData: IStackTraceData[] = [];
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @param blockScopeBody
|
|
|
|
- */
|
|
|
|
- constructor (blockScopeBody: ESTree.Node[]) {
|
|
|
|
- this.blockScopeBody = blockScopeBody;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @returns {T}
|
|
|
|
- */
|
|
|
|
- public analyze (): IStackTraceData[] {
|
|
|
|
- if (this.blockScopeBody.length === 1) {
|
|
|
|
- estraverse.traverse(this.blockScopeBody[0], {
|
|
|
|
- enter: (node: ESTree.Node): any => {
|
|
|
|
- if (Nodes.isBlockStatementNode(node)) {
|
|
|
|
- this.analyzeRecursive(node.body, this.stackTraceData);
|
|
|
|
-
|
|
|
|
- return estraverse.VisitorOption.Skip;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- } else {
|
|
|
|
- this.analyzeRecursive(this.blockScopeBody, this.stackTraceData);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return this.stackTraceData;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @param blockScopeBody
|
|
|
|
- * @param stackTraceData
|
|
|
|
- */
|
|
|
|
- private analyzeRecursive (blockScopeBody: ESTree.Node[], stackTraceData: IStackTraceData[]): void {
|
|
|
|
- for (let rootNode of blockScopeBody) {
|
|
|
|
- estraverse.traverse(rootNode, {
|
|
|
|
- enter: (node: ESTree.Node): any => {
|
|
|
|
- let calleeNode: TNodeWithBlockStatement|null = null,
|
|
|
|
- name: string = '';
|
|
|
|
-
|
|
|
|
- if (Nodes.isCallExpressionNode(node) && rootNode.parentNode === NodeUtils.getBlockScopeOfNode(node)) {
|
|
|
|
- if (Nodes.isIdentifierNode(node.callee)) {
|
|
|
|
- calleeNode = this.getCalleeBlockStatement(
|
|
|
|
- NodeUtils.getBlockScopeOfNode(blockScopeBody[0]),
|
|
|
|
- node.callee.name
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- name = node.callee.name;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!calleeNode) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const data: IStackTraceData = {
|
|
|
|
- callee: calleeNode,
|
|
|
|
- name: name,
|
|
|
|
- stackTrace: []
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- stackTraceData.push(data);
|
|
|
|
-
|
|
|
|
- this.analyzeRecursive(calleeNode.body, data.stackTrace);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private getCalleeBlockStatement (node: ESTree.Node, name: string): TNodeWithBlockStatement|null {
|
|
|
|
- let calleeBlockStatement: TNodeWithBlockStatement|null = null;
|
|
|
|
-
|
|
|
|
- estraverse.traverse(node, {
|
|
|
|
- enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
|
|
|
|
- if (Nodes.isFunctionDeclarationNode(node) && node.id.name === name) {
|
|
|
|
- calleeBlockStatement = node.body;
|
|
|
|
-
|
|
|
|
- return estraverse.VisitorOption.Break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (
|
|
|
|
- Nodes.isFunctionExpressionNode(node) &&
|
|
|
|
- Nodes.isVariableDeclaratorNode(parentNode) &&
|
|
|
|
- Nodes.isIdentifierNode(parentNode.id) &&
|
|
|
|
- parentNode.id.name === name
|
|
|
|
- ) {
|
|
|
|
- calleeBlockStatement = node.body;
|
|
|
|
-
|
|
|
|
- return estraverse.VisitorOption.Break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- return calleeBlockStatement;
|
|
|
|
- }
|
|
|
|
-}
|
|
|