refactoring
Version:
JavaScript Refactoring Tools
140 lines (104 loc) • 4.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _esprima = require('esprima');
var _esprima2 = _interopRequireDefault(_esprima);
var _estraverse = require('estraverse');
var _estraverse2 = _interopRequireDefault(_estraverse);
var _escodegen = require('escodegen');
var _escodegen2 = _interopRequireDefault(_escodegen);
var _chance = require('chance');
var _chance2 = _interopRequireDefault(_chance);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var chance = new _chance2.default();
var defaults = {
input: '',
client: {
startCode: function startCode(id) {
return 'inst.start(\'' + id + '\')';
},
endCode: function endCode(id) {
return 'inst.end(\'' + id + '\')';
}
},
escodegenOptions: {
format: {
indent: {
style: ' '
}
}
}
};
var Instrumenter = function () {
function Instrumenter(params) {
_classCallCheck(this, Instrumenter);
params = Object.assign({}, defaults, params);
this.input = params.input;
this.client = params.client;
this.escodegenOptions = params.escodegenOptions;
this.ast = null;
this.output = '';
this.ast = _esprima2.default.parse(this.input);
}
_createClass(Instrumenter, [{
key: 'instrument',
value: function instrument() {
var _this = this;
_estraverse2.default.traverse(this.ast, {
enter: function enter(node, parent) {
var id = chance.guid(),
body = null;
var clientStartAst = _esprima2.default.parse(typeof _this.client.startCode === 'function' ? _this.client.startCode(id) : _this.client.startCode);
var clientEndAst = _esprima2.default.parse(typeof _this.client.endCode === 'function' ? _this.client.endCode(id) : _this.client.endCode);
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
body = node.body.body;
if (!body) {
throw new Error('No body found for function');
}
body.unshift(clientStartAst);
if (body[body.length - 1].type !== 'ReturnStatement' && body[body.length - 1].type !== 'ThrowStatement') {
body.push(clientEndAst);
}
_estraverse2.default.traverse(node.body, {
enter: function enter(node, parent) {
var body = null;
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
return _estraverse2.default.VisitorOption.Skip;
}
if (node.type === 'ReturnStatement' || node.type === 'ThrowStatement') {
if (parent.type === 'BlockStatement') {
body = parent.body;
} else if (parent.type === 'IfStatement') {
if (parent.consequent.type !== 'BlockStatement') {
parent.consequent = {
type: 'BlockStatement',
body: [parent.consequent]
};
}
body = parent.consequent.body;
} else if (parent.type === 'SwitchCase') {
body = parent.consequent;
}
if (!body) {
throw new Error('No body found for return statement parent');
}
for (var l = body.length, i = l - 1; i >= 0; i--) {
if (body[i].type === 'ReturnStatement' || body[i].type === 'ThrowStatement') {
body.splice(i, 0, clientEndAst);
}
}
}
}
});
}
}
});
return _escodegen2.default.generate(this.ast, this.escodegenOptions);
}
}]);
return Instrumenter;
}();
exports.default = Instrumenter;