UNPKG

5.25 kBJavaScriptView Raw
1var astUtils = require('sl-esprima-ast-utils');
2var md5 = require('md5');
3var babelGenerator = require("@babel/generator");
4var traverse = require('ast-traverse');
5var AstNodeTypes = require("./ast-node-types");
6var utils = require("../utils");
7
8/**
9 * Creates branch object from node received from ast
10 * @param node
11 * @param parentNode
12 * @param type
13 * @param index
14 * @param absolutePath
15 * @param relativePath
16 * @param logger
17 * @constructor
18 */
19var METHOD_INDEX_FOR_GLOBAL_BRANCHES = -1;
20function BranchSignature(node, parentNode, type, index, absolutePath, relativePath, isGlobalBranch, activeMethodIndex, logger) {
21 this.node = node;
22 this.parentNode = parentNode;
23 this.index = index;
24 this.isGlobalBranch = isGlobalBranch;
25 this.activeMethodIndex = activeMethodIndex;
26 this.logger = logger;
27 this.generatedData = new BranchData(absolutePath, relativePath);
28 this.srcData = new BranchData();
29 this.type = type;
30 this.shouldSkip = false;
31 this.techSpecificInfo = {};
32 this.hasSourceData = false;
33}
34
35BranchSignature.prototype._createSignature = function () {
36 this.generatedData.position = formatLocationToArray(this.node.loc.start);
37 this.generatedData.endPosition = formatLocationToArray(this.node.loc.end);
38 this.generatedData.hash = this.calculateHash();
39 var parentPosition = this.resolveParentPosition();
40 this.generatedData.parentPosition = formatLocationToArray(parentPosition)
41 this.srcData = utils.cloneObject(this.generatedData, this.logger);
42 this.enclosingMethodIdx = this.getEnclosingMethodIdx();
43}
44
45BranchSignature.prototype.calculateHash = function () {
46 var clonedNode = astUtils.clone(this.node);
47 // Visit node in pre order and calculate body hash.
48 traverse(clonedNode, {
49 pre: function (node) {
50 // If current node is the root node given return (we want to calculate the body hash only).
51 if (node == clonedNode)
52 return;
53 if (AstNodeTypes.isMethodNode(node)) {
54 emptyMethodNode(node);
55 }
56 emptyBranchNode(node);
57 }
58 });
59 var generatedCode = this.generateCodeFromAST(clonedNode);
60 return md5(generatedCode);
61};
62
63
64BranchSignature.prototype.generateCodeFromAST = function (node) {
65 return babelGenerator.default(node, {
66 comments: false
67 }, '').code;
68
69};
70
71//In case of AstNodeTypes.IfStatement Istanbul reports in runtime on the location of the parent node.
72BranchSignature.prototype.resolveParentPosition = function() {
73 if (this.type === AstNodeTypes.IfStatement){
74 return this.parentNode.loc.start;
75 } else {
76 return this.node.loc.start;
77 }
78};
79
80BranchSignature.prototype.createUniqueId = function() {
81 var relevantData = this.hasSourceData ? this.srcData : this.generatedData;
82 return [relevantData.relativeFilename, relevantData.parentPosition.join(','), this.index].join('|')
83};
84
85// Returns the global index of containing folder, its a global branch returns -1
86BranchSignature.prototype.getEnclosingMethodIdx = function() {
87 if(!this.isGlobalBranch){
88 return this.activeMethodIndex
89 }
90 return METHOD_INDEX_FOR_GLOBAL_BRANCHES;
91};
92
93
94BranchSignature.prototype.createDTO = function() {
95 return {
96 index: this.index,
97 type: this.type,
98 srcData: this.srcData,
99 generatedData: this.generatedData,
100 uniqueId: this.createUniqueId(),
101 enclosingMethodIdx: this.enclosingMethodIdx,
102 techSpecificInfo: this.techSpecificInfo
103 }
104};
105
106BranchSignature.create = function (node, parentNode, type, index, absolutePath, relativePath, isGlobalBranch, activeMethodIndex, logger) {
107 var signature = new this(node, parentNode, type, index, absolutePath, relativePath, isGlobalBranch, activeMethodIndex, logger);
108 signature._createSignature();
109 return signature;
110}
111
112
113function formatLocationToArray(loc) {
114 return [loc.line, loc.column];
115}
116
117function BranchData(absolutePath, relativePath) {
118 this.position = null;
119 this.endPosition = null;
120 this.hash = null;
121 this.parentPosition = null;
122 this.relativeFilename = relativePath;
123 this.absoluteFilename = absolutePath;
124}
125
126function emptyMethodNode (node) {
127 node.body = {
128 type: AstNodeTypes.BlockStatement,
129 body: []
130 }
131 node.params = [];
132 node.id = {
133 name: '_',
134 type: AstNodeTypes.Identifier
135 };
136};
137function emptyBranchNode(node) {
138 switch (node.type) {
139 case AstNodeTypes.IfStatement:
140 case AstNodeTypes.ConditionalExpression:
141 node.consequent = createEmptyBlock();
142 node.alternate = createEmptyBlock();
143 break;
144 case AstNodeTypes.SwitchStatement:
145 node.cases = [];
146 break;
147 case AstNodeTypes.LogicalExpression:
148 node.operator = "";
149 node.left = {
150 type: AstNodeTypes.StringLiteral,
151 value: null
152 };
153 node.right = {
154 type: AstNodeTypes.StringLiteral,
155 value: null
156 };
157 break;
158 }
159}
160function createEmptyBlock() {
161 return {
162 type: AstNodeTypes.BlockStatement,
163 body: []
164 }
165}
166module.exports = BranchSignature;
\No newline at end of file