You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.9 KiB
JavaScript

'use strict';
var t = require('babel-types');
var template = require('babel-template');
var wrapWithHelper = template([
'HELPER_ID(function () {',
' return EXP;',
'}, {',
' line: LINE,',
' column: COLUMN,',
' source: SOURCE,',
' filename: FILE',
'});'
].join('\n'));
var buildHelper = template([
'function HELPER_ID(fn, data) {',
' try {',
' return fn();',
' } catch (e) {',
' var type = typeof e;',
' if (e !== null && (type === "object" || type === "function")) {',
' try {',
' Object.defineProperty(e, "_avaThrowsHelperData", {',
' value: data',
' });',
' } catch (e) {}',
' }',
' throw e;',
' }',
'}'
].join('\n'));
var assertionVisitor = {
CallExpression: function (path, state) {
if (isThrowsMember(path.get('callee'))) {
var arg0 = path.node.arguments[0];
path.node.arguments[0] = wrapWithHelper({
HELPER_ID: t.identifier(this.avaThrowHelper()),
EXP: arg0,
LINE: t.numericLiteral(arg0.loc.start.line),
COLUMN: t.numericLiteral(arg0.loc.start.column),
SOURCE: t.stringLiteral(state.file.code.substring(arg0.start, arg0.end)),
FILE: t.stringLiteral(state.file.opts.filename)
}).expression;
}
}
};
module.exports = function () {
return {
visitor: {
Program: function (path, state) {
var HELPER_ID = path.scope.generateUid('avaThrowsHelper');
var created = false;
path.traverse(assertionVisitor, {
avaThrowHelper: function () {
if (!created) {
created = true;
path.unshiftContainer('body', buildHelper({
HELPER_ID: t.identifier(HELPER_ID)
}));
}
return HELPER_ID;
},
file: state.file
});
}
}
};
};
function isThrowsMember(path) {
return path.isMemberExpression() && path.get('object').isIdentifier({name: 't'}) && (
path.get('property').isIdentifier({name: 'throws'}) ||
path.get('property').isIdentifier({name: 'notThrows'})
);
}