Skip to content
Permalink
9bfb9ba527
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
184 lines (158 sloc) 5.81 KB
/**
* @fileoverview A rule to set the maximum number of statements in a function.
* @author Ian Christian Myers
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
const { upperCaseFirst } = require("../shared/string-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Enforce a maximum number of statements allowed in function blocks",
recommended: false,
url: "https://eslint.org/docs/latest/rules/max-statements"
},
schema: [
{
oneOf: [
{
type: "integer",
minimum: 0
},
{
type: "object",
properties: {
maximum: {
type: "integer",
minimum: 0
},
max: {
type: "integer",
minimum: 0
}
},
additionalProperties: false
}
]
},
{
type: "object",
properties: {
ignoreTopLevelFunctions: {
type: "boolean"
}
},
additionalProperties: false
}
],
messages: {
exceed: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}."
}
},
create(context) {
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
const functionStack = [],
option = context.options[0],
ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false,
topLevelFunctions = [];
let maxStatements = 10;
if (
typeof option === "object" &&
(Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
) {
maxStatements = option.maximum || option.max;
} else if (typeof option === "number") {
maxStatements = option;
}
/**
* Reports a node if it has too many statements
* @param {ASTNode} node node to evaluate
* @param {int} count Number of statements in node
* @param {int} max Maximum number of statements allowed
* @returns {void}
* @private
*/
function reportIfTooManyStatements(node, count, max) {
if (count > max) {
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(node));
context.report({
node,
messageId: "exceed",
data: { name, count, max }
});
}
}
/**
* When parsing a new function, store it in our function stack
* @returns {void}
* @private
*/
function startFunction() {
functionStack.push(0);
}
/**
* Evaluate the node at the end of function
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function endFunction(node) {
const count = functionStack.pop();
/*
* This rule does not apply to class static blocks, but we have to track them so
* that statements in them do not count as statements in the enclosing function.
*/
if (node.type === "StaticBlock") {
return;
}
if (ignoreTopLevelFunctions && functionStack.length === 0) {
topLevelFunctions.push({ node, count });
} else {
reportIfTooManyStatements(node, count, maxStatements);
}
}
/**
* Increment the count of the functions
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function countStatements(node) {
functionStack[functionStack.length - 1] += node.body.length;
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
FunctionDeclaration: startFunction,
FunctionExpression: startFunction,
ArrowFunctionExpression: startFunction,
StaticBlock: startFunction,
BlockStatement: countStatements,
"FunctionDeclaration:exit": endFunction,
"FunctionExpression:exit": endFunction,
"ArrowFunctionExpression:exit": endFunction,
"StaticBlock:exit": endFunction,
"Program:exit"() {
if (topLevelFunctions.length === 1) {
return;
}
topLevelFunctions.forEach(element => {
const count = element.count;
const node = element.node;
reportIfTooManyStatements(node, count, maxStatements);
});
}
};
}
};