blob: e52bd1dd20723e277087e537c1dfc1aba1aae3ee [file] [log] [blame]
Jack Franklin8b9aa2f2020-02-12 16:35:15 +00001'use strict';
2
3/* eslint "complexity": [ "error", 5 ] */
4
5/**
6 * @fileoverview Disallow async functions as arguments to describe
7 */
8
Tim van der Lippe16aca392020-11-13 11:37:13 +00009const createAstUtils = require('../util/ast');
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000010
Tim van der Lippe16aca392020-11-13 11:37:13 +000011module.exports = {
12 meta: {
13 type: 'problem',
14 docs: {
15 description: 'Disallow async functions passed to describe'
16 },
17 fixable: 'code'
18 },
19 create(context) {
20 const astUtils = createAstUtils(context.settings);
21 const sourceCode = context.getSourceCode();
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000022
Tim van der Lippe16aca392020-11-13 11:37:13 +000023 function isFunction(node) {
24 return (
25 node.type === 'FunctionExpression' ||
26 node.type === 'FunctionDeclaration' ||
27 node.type === 'ArrowFunctionExpression'
28 );
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000029 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000030
Tim van der Lippe16aca392020-11-13 11:37:13 +000031 function containsDirectAwait(node) {
32 if (node.type === 'AwaitExpression') {
33 return true;
34 } else if (node.type && !isFunction(node)) {
35 return Object.keys(node).some(function (key) {
36 if (Array.isArray(node[key])) {
37 return node[key].some(containsDirectAwait);
38 } else if (key !== 'parent' && node[key] && typeof node[key] === 'object') {
39 return containsDirectAwait(node[key]);
40 }
41 return false;
42 });
43 }
44 return false;
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000045 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000046
Tim van der Lippe16aca392020-11-13 11:37:13 +000047 function fixAsyncFunction(fixer, fn) {
48 if (!containsDirectAwait(fn.body)) {
49 // Remove the "async" token and all the whitespace before "function":
50 const [ asyncToken, functionToken ] = sourceCode.getFirstTokens(fn, 2);
51 return fixer.removeRange([ asyncToken.range[0], functionToken.range[0] ]);
52 }
53 return undefined;
54 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000055
Tim van der Lippe16aca392020-11-13 11:37:13 +000056 function isAsyncFunction(node) {
57 return node && (node.type === 'FunctionExpression' ||
58 node.type === 'ArrowFunctionExpression') && node.async;
59 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000060
Tim van der Lippe16aca392020-11-13 11:37:13 +000061 return {
62 CallExpression(node) {
63 const name = astUtils.getNodeName(node.callee);
64
65 if (astUtils.isDescribe(node)) {
66 const fnArg = node.arguments.slice(-1)[0];
67 if (isAsyncFunction(fnArg)) {
68 context.report({
69 node: fnArg,
70 message: `Unexpected async function in ${name}()`,
71 fix(fixer) {
72 return fixAsyncFunction(fixer, fnArg);
73 }
74 });
75 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000076 }
77 }
Tim van der Lippe16aca392020-11-13 11:37:13 +000078 };
79 }
Jack Franklin8b9aa2f2020-02-12 16:35:15 +000080};