text: 'use strict';
  
  module.exports = babelCore => {
  	const t = babelCore.types;
  	const wrapArg = babelCore.template('(START(t, ASSERTION, FILE, LINE), END(t, ARG))');
  	const helpers = babelCore.template(`function START(t, assertion, file, line) {
    if (t._throwsArgStart) {
      t._throwsArgStart(assertion, file, line);
    }
  }
  
  function END(t, arg) {
    if (t._throwsArgEnd) {
      t._throwsArgEnd();
    }
  
    return arg;
  }`);
  
  	const assertionVisitor = {
  		CallExpression(path, state) {
  			const callee = path.get('callee');
  			if (!callee.isMemberExpression() || !callee.get('object').isIdentifier({name: 't'}) || !callee.get('property').isIdentifier()) {
  				return;
  			}
  
  			const assertion = callee.get('property').get('name').node;
  			if (assertion !== 'throws' && assertion !== 'notThrows') {
  				return;
  			}
  
  			const arg0 = path.node.arguments[0];
  			if (!(arg0 && arg0.loc && (typeof arg0.start === 'number') && (typeof arg0.end === 'number'))) {
  				return;
  			}
  
  			// Wrap the argument expression, so that the stack trace of the assertion
  			// isn't affected.
  			path.node.arguments[0] = wrapArg(Object.assign({
  				ARG: arg0,
  				ASSERTION: t.stringLiteral(assertion),
  				FILE: t.stringLiteral(state.file.opts.filename),
  				LINE: t.numericLiteral(arg0.loc.start.line)
  			}, this.installHelper())).expression;
  		}
  	};
  
  	return {
  		visitor: {
  			Program(path, state) {
  				const START = t.identifier(path.scope.generateUid('avaThrowsHelperStart'));
  				const END = t.identifier(path.scope.generateUid('avaThrowsHelperEnd'));
  				const helperIdentifiers = {START, END};
  
  				let created = false;
  				path.traverse(assertionVisitor, {
  					installHelper() {
  						if (!created) {
  							created = true;
  							path.unshiftContainer('body', helpers(helperIdentifiers));
  						}
  
  						return helperIdentifiers;
  					},
  					file: state.file
  				});
  			}
  		}
  	};
  };
  