UNPKG

eslint-plugin-mocha

Version:

Eslint rules for mocha.

81 lines 3.87 kB
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