UNPKG

3.53 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to enforce a maximum number of nested callbacks.
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 callbacks can be nested",
16 category: "Stylistic Issues",
17 recommended: false,
18 url: "https://eslint.org/docs/rules/max-nested-callbacks"
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 // Constants
51 //--------------------------------------------------------------------------
52 const option = context.options[0];
53 let THRESHOLD = 10;
54
55 if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") {
56 THRESHOLD = option.maximum;
57 }
58 if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") {
59 THRESHOLD = option.max;
60 }
61 if (typeof option === "number") {
62 THRESHOLD = option;
63 }
64
65 //--------------------------------------------------------------------------
66 // Helpers
67 //--------------------------------------------------------------------------
68
69 const callbackStack = [];
70
71 /**
72 * Checks a given function node for too many callbacks.
73 * @param {ASTNode} node The node to check.
74 * @returns {void}
75 * @private
76 */
77 function checkFunction(node) {
78 const parent = node.parent;
79
80 if (parent.type === "CallExpression") {
81 callbackStack.push(node);
82 }
83
84 if (callbackStack.length > THRESHOLD) {
85 const opts = { num: callbackStack.length, max: THRESHOLD };
86
87 context.report({ node, message: "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", data: opts });
88 }
89 }
90
91 /**
92 * Pops the call stack.
93 * @returns {void}
94 * @private
95 */
96 function popStack() {
97 callbackStack.pop();
98 }
99
100 //--------------------------------------------------------------------------
101 // Public API
102 //--------------------------------------------------------------------------
103
104 return {
105 ArrowFunctionExpression: checkFunction,
106 "ArrowFunctionExpression:exit": popStack,
107
108 FunctionExpression: checkFunction,
109 "FunctionExpression:exit": popStack
110 };
111
112 }
113};