1 | var astUtils = require('sl-esprima-ast-utils');
|
2 | var md5 = require('md5');
|
3 | var babelGenerator = require("@babel/generator");
|
4 | var traverse = require('ast-traverse');
|
5 | var AstNodeTypes = require("./ast-node-types");
|
6 | var utils = require("../utils");
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | var METHOD_INDEX_FOR_GLOBAL_BRANCHES = -1;
|
20 | function 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 |
|
35 | BranchSignature.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 |
|
45 | BranchSignature.prototype.calculateHash = function () {
|
46 | var clonedNode = astUtils.clone(this.node);
|
47 |
|
48 | traverse(clonedNode, {
|
49 | pre: function (node) {
|
50 |
|
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 |
|
64 | BranchSignature.prototype.generateCodeFromAST = function (node) {
|
65 | return babelGenerator.default(node, {
|
66 | comments: false
|
67 | }, '').code;
|
68 |
|
69 | };
|
70 |
|
71 |
|
72 | BranchSignature.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 |
|
80 | BranchSignature.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 |
|
86 | BranchSignature.prototype.getEnclosingMethodIdx = function() {
|
87 | if(!this.isGlobalBranch){
|
88 | return this.activeMethodIndex
|
89 | }
|
90 | return METHOD_INDEX_FOR_GLOBAL_BRANCHES;
|
91 | };
|
92 |
|
93 |
|
94 | BranchSignature.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 |
|
106 | BranchSignature.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 |
|
113 | function formatLocationToArray(loc) {
|
114 | return [loc.line, loc.column];
|
115 | }
|
116 |
|
117 | function 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 |
|
126 | function 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 | };
|
137 | function 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 | }
|
160 | function createEmptyBlock() {
|
161 | return {
|
162 | type: AstNodeTypes.BlockStatement,
|
163 | body: []
|
164 | }
|
165 | }
|
166 | module.exports = BranchSignature; |
\ | No newline at end of file |