UNPKG

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