UNPKG

2.33 kBJavaScriptView Raw
1'use strict';
2
3/* eslint "complexity": [ "error", 5 ] */
4
5/**
6 * @fileoverview Disallow async functions as arguments to describe
7 */
8
9const astUtils = require('../util/ast');
10const { additionalSuiteNames } = require('../util/settings');
11
12module.exports = function (context) {
13 const sourceCode = context.getSourceCode();
14
15 function isFunction(node) {
16 return (
17 node.type === 'FunctionExpression' ||
18 node.type === 'FunctionDeclaration' ||
19 node.type === 'ArrowFunctionExpression'
20 );
21 }
22
23 function containsDirectAwait(node) {
24 if (node.type === 'AwaitExpression') {
25 return true;
26 } else if (node.type && !isFunction(node)) {
27 return Object.keys(node).some(function (key) {
28 if (Array.isArray(node[key])) {
29 return node[key].some(containsDirectAwait);
30 } else if (key !== 'parent' && node[key] && typeof node[key] === 'object') {
31 return containsDirectAwait(node[key]);
32 }
33 return false;
34 });
35 }
36 return false;
37 }
38
39 function fixAsyncFunction(fixer, fn) {
40 if (!containsDirectAwait(fn.body)) {
41 // Remove the "async" token and all the whitespace before "function":
42 const [ asyncToken, functionToken ] = sourceCode.getFirstTokens(fn, 2);
43 return fixer.removeRange([ asyncToken.range[0], functionToken.range[0] ]);
44 }
45 return undefined;
46 }
47
48 function isAsyncFunction(node) {
49 return node && (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') && node.async;
50 }
51
52 return {
53 CallExpression(node) {
54 const name = astUtils.getNodeName(node.callee);
55
56 if (astUtils.isDescribe(node, additionalSuiteNames(context.settings))) {
57 const fnArg = node.arguments.slice(-1)[0];
58 if (isAsyncFunction(fnArg)) {
59 context.report({
60 node: fnArg,
61 message: `Unexpected async function in ${name}()`,
62 fix(fixer) {
63 return fixAsyncFunction(fixer, fnArg);
64 }
65 });
66 }
67 }
68 }
69 };
70};