UNPKG

5.53 kBJavaScriptView Raw
1/**
2 * @fileoverview A rule to set the maximum number of statements in a function.
3 * @author Ian Christian Myers
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
11
12const lodash = require("lodash");
13
14const astUtils = require("./utils/ast-utils");
15
16//------------------------------------------------------------------------------
17// Rule Definition
18//------------------------------------------------------------------------------
19
20module.exports = {
21 meta: {
22 type: "suggestion",
23
24 docs: {
25 description: "enforce a maximum number of statements allowed in function blocks",
26 category: "Stylistic Issues",
27 recommended: false,
28 url: "https://eslint.org/docs/rules/max-statements"
29 },
30
31 schema: [
32 {
33 oneOf: [
34 {
35 type: "integer",
36 minimum: 0
37 },
38 {
39 type: "object",
40 properties: {
41 maximum: {
42 type: "integer",
43 minimum: 0
44 },
45 max: {
46 type: "integer",
47 minimum: 0
48 }
49 },
50 additionalProperties: false
51 }
52 ]
53 },
54 {
55 type: "object",
56 properties: {
57 ignoreTopLevelFunctions: {
58 type: "boolean"
59 }
60 },
61 additionalProperties: false
62 }
63 ],
64 messages: {
65 exceed: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}."
66 }
67 },
68
69 create(context) {
70
71 //--------------------------------------------------------------------------
72 // Helpers
73 //--------------------------------------------------------------------------
74
75 const functionStack = [],
76 option = context.options[0],
77 ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false,
78 topLevelFunctions = [];
79 let maxStatements = 10;
80
81 if (
82 typeof option === "object" &&
83 (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
84 ) {
85 maxStatements = option.maximum || option.max;
86 } else if (typeof option === "number") {
87 maxStatements = option;
88 }
89
90 /**
91 * Reports a node if it has too many statements
92 * @param {ASTNode} node node to evaluate
93 * @param {int} count Number of statements in node
94 * @param {int} max Maximum number of statements allowed
95 * @returns {void}
96 * @private
97 */
98 function reportIfTooManyStatements(node, count, max) {
99 if (count > max) {
100 const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
101
102 context.report({
103 node,
104 messageId: "exceed",
105 data: { name, count, max }
106 });
107 }
108 }
109
110 /**
111 * When parsing a new function, store it in our function stack
112 * @returns {void}
113 * @private
114 */
115 function startFunction() {
116 functionStack.push(0);
117 }
118
119 /**
120 * Evaluate the node at the end of function
121 * @param {ASTNode} node node to evaluate
122 * @returns {void}
123 * @private
124 */
125 function endFunction(node) {
126 const count = functionStack.pop();
127
128 if (ignoreTopLevelFunctions && functionStack.length === 0) {
129 topLevelFunctions.push({ node, count });
130 } else {
131 reportIfTooManyStatements(node, count, maxStatements);
132 }
133 }
134
135 /**
136 * Increment the count of the functions
137 * @param {ASTNode} node node to evaluate
138 * @returns {void}
139 * @private
140 */
141 function countStatements(node) {
142 functionStack[functionStack.length - 1] += node.body.length;
143 }
144
145 //--------------------------------------------------------------------------
146 // Public API
147 //--------------------------------------------------------------------------
148
149 return {
150 FunctionDeclaration: startFunction,
151 FunctionExpression: startFunction,
152 ArrowFunctionExpression: startFunction,
153
154 BlockStatement: countStatements,
155
156 "FunctionDeclaration:exit": endFunction,
157 "FunctionExpression:exit": endFunction,
158 "ArrowFunctionExpression:exit": endFunction,
159
160 "Program:exit"() {
161 if (topLevelFunctions.length === 1) {
162 return;
163 }
164
165 topLevelFunctions.forEach(element => {
166 const count = element.count;
167 const node = element.node;
168
169 reportIfTooManyStatements(node, count, maxStatements);
170 });
171 }
172 };
173
174 }
175};