UNPKG

2.35 kBJavaScriptView Raw
1'use strict';
2
3/**
4 * @fileoverview Disallow arrow functions as arguments to Mocha globals
5 * @author Paul Melnikow
6 */
7
8const last = require('ramda/src/last');
9const astUtils = require('../util/ast');
10
11module.exports = function (context) {
12 const sourceCode = context.getSourceCode();
13
14 function formatFunctionHead(fn) {
15 const paramsLeftParen = sourceCode.getFirstToken(fn);
16 const paramsRightParen = sourceCode.getTokenBefore(sourceCode.getTokenBefore(fn.body));
17 let paramsFullText = sourceCode.text.slice(paramsLeftParen.range[0], paramsRightParen.range[1]);
18 let functionKeyword = 'function';
19
20 if (fn.async) {
21 // When 'async' specified, take care about the keyword.
22 functionKeyword = 'async function';
23 // Strip 'async (...)' to ' (...)'
24 paramsFullText = paramsFullText.slice(5);
25 }
26
27 if (fn.params.length > 0) {
28 paramsFullText = `(${ sourceCode.text.slice(fn.params[0].start, last(fn.params).end) })`;
29 }
30
31 return `${functionKeyword}${paramsFullText} `;
32 }
33
34 function fixArrowFunction(fixer, fn) {
35 if (fn.body.type === 'BlockStatement') {
36 // When it((...) => { ... }),
37 // simply replace '(...) => ' with 'function () '
38 return fixer.replaceTextRange(
39 [ fn.start, fn.body.start ],
40 formatFunctionHead(fn)
41 );
42 }
43
44 const bodyText = sourceCode.text.slice(fn.body.range[0], fn.body.range[1]);
45 return fixer.replaceTextRange(
46 [ fn.start, fn.end ],
47 `${formatFunctionHead(fn)}{ return ${ bodyText }; }`
48 );
49 }
50
51 return {
52 CallExpression(node) {
53 const name = astUtils.getNodeName(node.callee);
54
55 if (astUtils.isMochaFunctionCall(node, context.getScope())) {
56 const fnArg = node.arguments.slice(-1)[0];
57 if (fnArg && fnArg.type === 'ArrowFunctionExpression') {
58 context.report({
59 node,
60 message: `Do not pass arrow functions to ${ name }()`,
61 fix(fixer) {
62 return fixArrowFunction(fixer, fnArg);
63 }
64 });
65 }
66 }
67 }
68 };
69};