1 |
|
2 | (function() {
|
3 | var escodegen, estools, ftools, tools, _;
|
4 |
|
5 | _ = require('underscore');
|
6 |
|
7 | escodegen = require('escodegen');
|
8 |
|
9 | tools = require('./tools');
|
10 |
|
11 | estools = require('./estools');
|
12 |
|
13 | ftools = require('./jscoverage-formatting-tools');
|
14 |
|
15 | exports.formatTree = function(ast) {
|
16 | ftools.evalLiterals(ast, [
|
17 | {
|
18 | test: function(node) {
|
19 | return node.type === 'UnaryExpression' && node.argument.type === 'Literal' && node.operator === '!';
|
20 | },
|
21 | "eval": function(node) {
|
22 | return !node.argument.value;
|
23 | }
|
24 | }, {
|
25 | test: function(node) {
|
26 | return node.type === 'UnaryExpression' && node.argument.type === 'Literal' && node.operator === "~" && typeof node.argument.value === 'number';
|
27 | },
|
28 | "eval": function(node) {
|
29 | return ~node.argument.value;
|
30 | }
|
31 | }, {
|
32 | test: function(node) {
|
33 | return node.type === 'BinaryExpression' && node.left.type === 'Literal' && node.right.type === 'Literal' && typeof node.left.value === 'string' && typeof node.right.value === 'string' && node.operator === '+';
|
34 | },
|
35 | "eval": function(node) {
|
36 | return node.left.value + node.right.value;
|
37 | }
|
38 | }, {
|
39 | test: function(node) {
|
40 | var _ref;
|
41 | return node.type === 'BinaryExpression' && ftools.isNumericLiteral(node.left) && ftools.isNumericLiteral(node.right) && ((_ref = node.operator) === '+' || _ref === '-' || _ref === '*' || _ref === '%' || _ref === '/' || _ref === '<<' || _ref === '>>' || _ref === '>>>') && typeof ftools.evalLiteral(node.left) === 'number' && typeof ftools.evalLiteral(node.right) === 'number';
|
42 | },
|
43 | "eval": function(node) {
|
44 | return ftools.evalBinaryExpression(ftools.evalLiteral(node.left), node.operator, ftools.evalLiteral(node.right));
|
45 | }
|
46 | }
|
47 | ]);
|
48 | estools.traverse(ast, ['MemberExpression'], function(node) {
|
49 | var _ref;
|
50 | if (node.property.type === 'Literal' && ftools.isValidIdentifier(node.property.value)) {
|
51 | node.computed = false;
|
52 | node.property = {
|
53 | type: 'Identifier',
|
54 | name: node.property.value
|
55 | };
|
56 | }
|
57 | if (node.property.type === 'Literal' && ((_ref = node.property.value) != null ? _ref.toString().match(/^[1-9][0-9]*$/) : void 0)) {
|
58 | node.computed = true;
|
59 | node.property = estools.createLiteral(parseInt(node.property.value, 10));
|
60 | }
|
61 | if (node.property.type === 'Identifier' && ftools.isReservedWord(node.property.name)) {
|
62 | node.computed = true;
|
63 | return node.property = estools.createLiteral(node.property.name);
|
64 | }
|
65 | });
|
66 | estools.traverse(ast, function(node) {
|
67 | var _ref;
|
68 | if (((_ref = node.test) != null ? _ref.type : void 0) === 'Literal') {
|
69 | if (node.type === 'ConditionalExpression') {
|
70 | if (typeof node.test.value === 'string' || typeof node.test.value === 'number' || typeof node.test.value === 'boolean') {
|
71 | if (node.test.value) {
|
72 | return tools.replaceProperties(node, node.consequent);
|
73 | } else {
|
74 | return tools.replaceProperties(node, node.alternate);
|
75 | }
|
76 | }
|
77 | } else if (node.type === 'WhileStatement') {
|
78 | return node.test.value = !!node.test.value;
|
79 | } else if (node.type === 'DoWhileStatement') {
|
80 | return node.test.value = !!node.test.value;
|
81 | } else if (node.type === 'ForStatement') {
|
82 | if (node.test.value) {
|
83 | return node.test = null;
|
84 | } else {
|
85 | return node.test.value = false;
|
86 | }
|
87 | }
|
88 | }
|
89 | });
|
90 | ftools.replaceNegativeInfinities(ast);
|
91 | ftools.replacePositiveInfinities(ast);
|
92 | estools.traverse(ast, ['BlockStatement', 'Program'], function(node) {
|
93 | return node.body = node.body.filter(function(x, i) {
|
94 | var _ref;
|
95 | return !(x.type === 'EmptyStatement' && i - 1 >= 0 && ((_ref = node.body[i - 1].type) === 'ReturnStatement' || _ref === 'VariableDeclaration' || _ref === 'ExpressionStatement') && node.body[i - 1].loc.end.line === x.loc.start.line);
|
96 | });
|
97 | });
|
98 | estools.traverse(ast, ['BlockStatement', 'Program'], function(node) {
|
99 | return node.body = _.flatten(node.body.map(function(x, i) {
|
100 | if (x.type === 'IfStatement' && x.test.type === 'Literal') {
|
101 | if (x.test.value) {
|
102 | if (x.consequent.type === 'BlockStatement') {
|
103 | return x.consequent.body;
|
104 | } else {
|
105 | return _.extend({}, x.consequent, {
|
106 | loc: x.loc
|
107 | });
|
108 | }
|
109 | } else if (x.alternate) {
|
110 | if (x.alternate.type === 'BlockStatement') {
|
111 | return x.alternate.body;
|
112 | } else {
|
113 | return _.extend({}, x.alternate, {
|
114 | loc: x.loc
|
115 | });
|
116 | }
|
117 | } else {
|
118 | return [];
|
119 | }
|
120 | } else {
|
121 | return x;
|
122 | }
|
123 | }));
|
124 | });
|
125 | return estools.traverse(ast, ['FunctionExpression', 'FunctionDeclaration', 'Program'], function(node) {
|
126 | var body;
|
127 | body = node.type === 'Program' ? node.body : node.body.body;
|
128 | return body.filter(function(x) {
|
129 | return x.type === 'VariableDeclaration' && x.kind === 'let';
|
130 | }).forEach(function(stm) {
|
131 | return stm.kind = 'var';
|
132 | });
|
133 | });
|
134 | };
|
135 |
|
136 | exports.postFormatTree = function(ast) {
|
137 | var stored;
|
138 | stored = [];
|
139 | estools.traverse(ast, ['BlockStatement'], function(node) {
|
140 | if (node.body.some(function(stm) {
|
141 | return stm.type === 'VariableDeclaration' && stm.kind === 'let';
|
142 | })) {
|
143 | return stored.push(node);
|
144 | }
|
145 | });
|
146 | return stored.forEach(function(node) {
|
147 | return node.body = [
|
148 | {
|
149 | type: 'BlockStatement',
|
150 | body: node.body,
|
151 | loc: node.loc
|
152 | }
|
153 | ];
|
154 | });
|
155 | };
|
156 |
|
157 | }).call(this);
|