eslint-plugin-mocha
Version:
Eslint rules for mocha.
114 lines • 4.6 kB
JavaScript
import { createMochaVisitors } from "../ast/mocha-visitors.js";
import { expectNodeRange } from "../ast/node-location.js";
import { isBlockStatement } from "../ast/node-types.js";
import { getLastOrThrow } from "../list.js";
import { getTopLevelMochaExpression, isDirectStatementInScope } from "./direct-mocha-statement.js";
const minimumAmountOfLinesBetweenNeeded = 2;
function containsNode(nodeA, nodeB) {
const rangeA = expectNodeRange(nodeA);
const rangeB = expectNodeRange(nodeB);
return rangeB[1] <= rangeA[1] && rangeB[0] >= rangeA[0];
}
function isFirstStatementInScope(scopeNode, node) {
const [firstNode] = scopeNode.body;
return firstNode === undefined || containsNode(firstNode, node);
}
function getSpacingCheck(currentLayer, entity) {
const { statementNode, beforeToken } = entity;
const statementNodeLocation = statementNode.loc;
if (beforeToken === null ||
statementNodeLocation === null ||
statementNodeLocation === undefined ||
isFirstStatementInScope(currentLayer.scopeNode, statementNode)) {
return undefined;
}
return {
beforeToken,
linesBetween: statementNodeLocation.start.line - beforeToken.loc.end.line,
reportNode: entity.reportNode
};
}
export const consistentSpacingBetweenBlocksRule = {
meta: {
type: 'suggestion',
docs: {
description: 'Require consistent spacing between blocks',
recommended: false,
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/documentation/rules/' +
'consistent-spacing-between-blocks.md'
},
fixable: 'whitespace',
schema: [],
messages: {
expectedLineBreak: 'Expected line break before this statement.'
},
languages: ['js/js']
},
create(context) {
const layers = [];
const { sourceCode } = context;
function addEntityToCurrentLayer(visitorContext) {
const currentLayer = getLastOrThrow(layers);
if (isDirectStatementInScope(currentLayer.scopeNode, visitorContext.node)) {
const statementNode = getTopLevelMochaExpression(visitorContext.node);
layers[layers.length - 1] = {
...currentLayer,
entities: [
...currentLayer.entities,
{
reportNode: visitorContext.node,
statementNode,
beforeToken: sourceCode.getTokenBefore(statementNode, { includeComments: false })
}
]
};
}
}
function checkCurrentLayer() {
const currentLayer = getLastOrThrow(layers);
for (const entity of currentLayer.entities) {
const spacingCheck = getSpacingCheck(currentLayer, entity);
if (spacingCheck !== undefined &&
spacingCheck.linesBetween < minimumAmountOfLinesBetweenNeeded) {
context.report({
node: spacingCheck.reportNode,
messageId: 'expectedLineBreak',
fix(fixer) {
return fixer.insertTextAfter(spacingCheck.beforeToken, spacingCheck.linesBetween === 0 ? '\n\n' : '\n');
}
});
}
}
}
return createMochaVisitors(context, {
suite(visitorContext) {
addEntityToCurrentLayer(visitorContext);
},
suiteCallback(visitorContext) {
const { node } = visitorContext;
if (isBlockStatement(node.body)) {
layers.push({ entities: [], scopeNode: node.body });
}
},
'suiteCallback:exit'(visitorContext) {
if (isBlockStatement(visitorContext.node.body)) {
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