UNPKG

4.62 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 url: "https://eslint.org/docs/rules/max-depth"
19 },
20
21 schema: [
22 {
23 oneOf: [
24 {
25 type: "integer",
26 minimum: 0
27 },
28 {
29 type: "object",
30 properties: {
31 maximum: {
32 type: "integer",
33 minimum: 0
34 },
35 max: {
36 type: "integer",
37 minimum: 0
38 }
39 },
40 additionalProperties: false
41 }
42 ]
43 }
44 ]
45 },
46
47 create(context) {
48
49 //--------------------------------------------------------------------------
50 // Helpers
51 //--------------------------------------------------------------------------
52
53 const functionStack = [],
54 option = context.options[0];
55 let maxDepth = 4;
56
57 if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
58 maxDepth = option.maximum;
59 }
60 if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") {
61 maxDepth = option.max;
62 }
63 if (typeof option === "number") {
64 maxDepth = option;
65 }
66
67 /**
68 * When parsing a new function, store it in our function stack
69 * @returns {void}
70 * @private
71 */
72 function startFunction() {
73 functionStack.push(0);
74 }
75
76 /**
77 * When parsing is done then pop out the reference
78 * @returns {void}
79 * @private
80 */
81 function endFunction() {
82 functionStack.pop();
83 }
84
85 /**
86 * Save the block and Evaluate the node
87 * @param {ASTNode} node node to evaluate
88 * @returns {void}
89 * @private
90 */
91 function pushBlock(node) {
92 const len = ++functionStack[functionStack.length - 1];
93
94 if (len > maxDepth) {
95 context.report({ node, message: "Blocks are nested too deeply ({{depth}}).", data: { 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};