UNPKG

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