UNPKG

4.57 kBJavaScriptView Raw
1/**
2 * @fileoverview A rule to set the maximum depth block can be nested 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 depth that blocks can be nested",
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 },
45
46 create(context) {
47
48 //--------------------------------------------------------------------------
49 // Helpers
50 //--------------------------------------------------------------------------
51
52 const functionStack = [],
53 option = context.options[0];
54 let maxDepth = 4;
55
56 if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
57 maxDepth = option.maximum;
58 }
59 if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") {
60 maxDepth = option.max;
61 }
62 if (typeof option === "number") {
63 maxDepth = option;
64 }
65
66 /**
67 * When parsing a new function, store it in our function stack
68 * @returns {void}
69 * @private
70 */
71 function startFunction() {
72 functionStack.push(0);
73 }
74
75 /**
76 * When parsing is done then pop out the reference
77 * @returns {void}
78 * @private
79 */
80 function endFunction() {
81 functionStack.pop();
82 }
83
84 /**
85 * Save the block and Evaluate the node
86 * @param {ASTNode} node node to evaluate
87 * @returns {void}
88 * @private
89 */
90 function pushBlock(node) {
91 const len = ++functionStack[functionStack.length - 1];
92
93 if (len > maxDepth) {
94 context.report(node, "Blocks are nested too deeply ({{depth}}).",
95 { depth: len });
96 }
97 }
98
99 /**
100 * Pop the saved block
101 * @returns {void}
102 * @private
103 */
104 function popBlock() {
105 functionStack[functionStack.length - 1]--;
106 }
107
108 //--------------------------------------------------------------------------
109 // Public API
110 //--------------------------------------------------------------------------
111
112 return {
113 Program: startFunction,
114 FunctionDeclaration: startFunction,
115 FunctionExpression: startFunction,
116 ArrowFunctionExpression: startFunction,
117
118 IfStatement(node) {
119 if (node.parent.type !== "IfStatement") {
120 pushBlock(node);
121 }
122 },
123 SwitchStatement: pushBlock,
124 TryStatement: pushBlock,
125 DoWhileStatement: pushBlock,
126 WhileStatement: pushBlock,
127 WithStatement: pushBlock,
128 ForStatement: pushBlock,
129 ForInStatement: pushBlock,
130 ForOfStatement: pushBlock,
131
132 "IfStatement:exit": popBlock,
133 "SwitchStatement:exit": popBlock,
134 "TryStatement:exit": popBlock,
135 "DoWhileStatement:exit": popBlock,
136 "WhileStatement:exit": popBlock,
137 "WithStatement:exit": popBlock,
138 "ForStatement:exit": popBlock,
139 "ForInStatement:exit": popBlock,
140 "ForOfStatement:exit": popBlock,
141
142 "FunctionDeclaration:exit": endFunction,
143 "FunctionExpression:exit": endFunction,
144 "ArrowFunctionExpression:exit": endFunction,
145 "Program:exit": endFunction
146 };
147
148 }
149};