eslint-plugin-mocha
Version:
Eslint rules for mocha.
81 lines • 3.87 kB
JavaScript
import { createMochaVisitors } from "../ast/mocha-visitors.js";
import { getParentNode, isArrowFunctionExpression } from "../ast/node-types.js";
function extractSourceTextByRange(sourceCode, start, end) {
return sourceCode.text.slice(start, end).trim();
}
function getTriviaBetweenArrowAndBody(sourceCode, fn) {
const arrow = sourceCode.getTokenBefore(fn.body);
return sourceCode.text.slice(arrow.range[1], fn.body.range[0]);
}
// eslint-disable-next-line max-statements -- we need to refactor this function to reduce complexity
function formatFunctionHead(sourceCode, fn, includeTriviaAfterArrow = true) {
const arrow = sourceCode.getTokenBefore(fn.body);
const beforeArrowToken = sourceCode.getTokenBefore(arrow);
let firstToken = sourceCode.getFirstToken(fn);
let functionKeyword = 'function';
let params = extractSourceTextByRange(sourceCode, firstToken.range[0], beforeArrowToken.range[1]);
if (fn.async === true) {
// When 'async' specified strip the token from the params text
// and prepend it to the function keyword
params = params.slice(firstToken.range[1] - firstToken.range[0]).trim();
functionKeyword = 'async function';
// Advance firstToken pointer
firstToken = sourceCode.getTokenAfter(firstToken);
}
const beforeArrowComment = extractSourceTextByRange(sourceCode, beforeArrowToken.range[1], arrow.range[0]);
const afterArrowComment = includeTriviaAfterArrow
? extractSourceTextByRange(sourceCode, arrow.range[1], fn.body.range[0])
: '';
const paramsFullText = firstToken.type === 'Punctuator'
? `${params}${beforeArrowComment}${afterArrowComment}`
: `(${params}${beforeArrowComment})${afterArrowComment}`;
return `${functionKeyword}${paramsFullText} `;
}
function fixArrowFunction(fixer, sourceCode, fn) {
if (fn.body.type === 'BlockStatement') {
// When it((...) => { ... }),
// simply replace '(...) => ' with 'function () '
return fixer.replaceTextRange([fn.range[0], fn.body.range[0]], formatFunctionHead(sourceCode, fn));
}
const triviaBetweenArrowAndBody = getTriviaBetweenArrowAndBody(sourceCode, fn);
const bodyText = sourceCode.getText(fn.body);
if (triviaBetweenArrowAndBody.includes('//')) {
return fixer.replaceTextRange(fn.range, `${formatFunctionHead(sourceCode, fn, false)}{${triviaBetweenArrowAndBody.replace(/^[ \t]+(?=\r?\n)/u, '')}return ${bodyText}; }`);
}
return fixer.replaceTextRange(fn.range, `${formatFunctionHead(sourceCode, fn)}{ return ${bodyText}; }`);
}
export const noMochaArrowsRule = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow arrow functions as arguments to mocha functions',
recommended: true,
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/documentation/rules/no-mocha-arrows.md'
},
fixable: 'code',
schema: [],
messages: {
unexpectedArrowFunction: 'Do not pass arrow functions to {{name}}'
},
languages: ['js/js']
},
create(context) {
const { sourceCode } = context;
return createMochaVisitors(context, {
anyTestEntityCallback(visitorContext) {
const { node } = visitorContext;
if (isArrowFunctionExpression(node)) {
context.report({
node: getParentNode(visitorContext.node),
messageId: 'unexpectedArrowFunction',
data: { name: visitorContext.name },
fix(fixer) {
return fixArrowFunction(fixer, sourceCode, node);
}
});
}
}
});
}
};
//# sourceMappingURL=no-mocha-arrows.js.map