eslint-plugin-mocha
Version:
Eslint rules for mocha.
95 lines • 3.75 kB
JavaScript
import { createMochaVisitors } from '../ast/mocha-visitors.js';
import { isBlockStatement, isFunction, isMemberExpression, isProgram } from '../ast/node-types.js';
import { getLastOrThrow } from '../list.js';
const minimumAmountOfLinesBetweenNeeded = 2;
function containsNode(nodeA, nodeB) {
const { range: rangeA } = nodeA;
const { range: rangeB } = nodeB;
if (rangeA === undefined || rangeB === undefined) {
return false;
}
return rangeB[1] <= rangeA[1] && rangeB[0] >= rangeA[0];
}
function isFirstStatementInScope(scopeNode, node) {
if (isBlockStatement(scopeNode) || isProgram(scopeNode)) {
const [firstNode] = scopeNode.body;
if (firstNode !== undefined) {
return containsNode(firstNode, node);
}
}
return containsNode(scopeNode, node);
}
function getParentWhileMemberExpression(node) {
if (isMemberExpression(node.parent)) {
return getParentWhileMemberExpression(node.parent);
}
return node;
}
export const consistentSpacingBetweenBlocksRule = {
meta: {
type: 'suggestion',
fixable: 'whitespace',
schema: [],
docs: {
description: 'Require consistent spacing between blocks',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/' +
'consistent-spacing-between-blocks.md'
}
},
create(context) {
const layers = [];
const { sourceCode } = context;
function addEntityToCurrentLayer(visitorContext) {
const currentLayer = getLastOrThrow(layers);
currentLayer.entities.push(visitorContext);
}
// eslint-disable-next-line complexity -- no idea how to refactor
function checkCurrentLayer() {
const currentLayer = getLastOrThrow(layers);
for (const entity of currentLayer.entities) {
const node = getParentWhileMemberExpression(entity.node);
const beforeToken = sourceCode.getTokenBefore(node);
if (!isFirstStatementInScope(currentLayer.scopeNode, node) && beforeToken !== null) {
const linesBetween = (node.loc?.start.line ?? 0) - (beforeToken.loc.end.line);
if (linesBetween < minimumAmountOfLinesBetweenNeeded) {
context.report({
node: entity.node,
message: 'Expected line break before this statement.',
fix(fixer) {
return fixer.insertTextAfter(beforeToken, linesBetween === 0 ? '\n\n' : '\n');
}
});
}
}
}
}
return createMochaVisitors(context, {
suite(visitorContext) {
addEntityToCurrentLayer(visitorContext);
},
suiteCallback(visitorContext) {
const { node } = visitorContext;
if (isFunction(node)) {
layers.push({ entities: [], scopeNode: node.body });
}
},
'suiteCallback:exit'() {
checkCurrentLayer();
layers.pop();
},
Program(node) {
layers.push({ entities: [], scopeNode: node });
},
'Program:exit'() {
checkCurrentLayer();
},
testCase(visitorContext) {
addEntityToCurrentLayer(visitorContext);
},
hook(visitorContext) {
addEntityToCurrentLayer(visitorContext);
}
});
}
};
//# sourceMappingURL=consistent-spacing-between-blocks.js.map