.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / complexity.js
1 /**
2  * @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity.
3  * Counts the number of if, conditional, for, while, try, switch/case,
4  * @author Patrick Brosset
5  */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Requirements
11 //------------------------------------------------------------------------------
12
13 const lodash = require("lodash");
14
15 const astUtils = require("./utils/ast-utils");
16
17 //------------------------------------------------------------------------------
18 // Rule Definition
19 //------------------------------------------------------------------------------
20
21 module.exports = {
22     meta: {
23         type: "suggestion",
24
25         docs: {
26             description: "enforce a maximum cyclomatic complexity allowed in a program",
27             category: "Best Practices",
28             recommended: false,
29             url: "https://eslint.org/docs/rules/complexity"
30         },
31
32         schema: [
33             {
34                 oneOf: [
35                     {
36                         type: "integer",
37                         minimum: 0
38                     },
39                     {
40                         type: "object",
41                         properties: {
42                             maximum: {
43                                 type: "integer",
44                                 minimum: 0
45                             },
46                             max: {
47                                 type: "integer",
48                                 minimum: 0
49                             }
50                         },
51                         additionalProperties: false
52                     }
53                 ]
54             }
55         ],
56
57         messages: {
58             complex: "{{name}} has a complexity of {{complexity}}. Maximum allowed is {{max}}."
59         }
60     },
61
62     create(context) {
63         const option = context.options[0];
64         let THRESHOLD = 20;
65
66         if (
67             typeof option === "object" &&
68             (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
69         ) {
70             THRESHOLD = option.maximum || option.max;
71         } else if (typeof option === "number") {
72             THRESHOLD = option;
73         }
74
75         //--------------------------------------------------------------------------
76         // Helpers
77         //--------------------------------------------------------------------------
78
79         // Using a stack to store complexity (handling nested functions)
80         const fns = [];
81
82         /**
83          * When parsing a new function, store it in our function stack
84          * @returns {void}
85          * @private
86          */
87         function startFunction() {
88             fns.push(1);
89         }
90
91         /**
92          * Evaluate the node at the end of function
93          * @param {ASTNode} node node to evaluate
94          * @returns {void}
95          * @private
96          */
97         function endFunction(node) {
98             const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
99             const complexity = fns.pop();
100
101             if (complexity > THRESHOLD) {
102                 context.report({
103                     node,
104                     messageId: "complex",
105                     data: { name, complexity, max: THRESHOLD }
106                 });
107             }
108         }
109
110         /**
111          * Increase the complexity of the function in context
112          * @returns {void}
113          * @private
114          */
115         function increaseComplexity() {
116             if (fns.length) {
117                 fns[fns.length - 1]++;
118             }
119         }
120
121         /**
122          * Increase the switch complexity in context
123          * @param {ASTNode} node node to evaluate
124          * @returns {void}
125          * @private
126          */
127         function increaseSwitchComplexity(node) {
128
129             // Avoiding `default`
130             if (node.test) {
131                 increaseComplexity();
132             }
133         }
134
135         //--------------------------------------------------------------------------
136         // Public API
137         //--------------------------------------------------------------------------
138
139         return {
140             FunctionDeclaration: startFunction,
141             FunctionExpression: startFunction,
142             ArrowFunctionExpression: startFunction,
143             "FunctionDeclaration:exit": endFunction,
144             "FunctionExpression:exit": endFunction,
145             "ArrowFunctionExpression:exit": endFunction,
146
147             CatchClause: increaseComplexity,
148             ConditionalExpression: increaseComplexity,
149             LogicalExpression: increaseComplexity,
150             ForStatement: increaseComplexity,
151             ForInStatement: increaseComplexity,
152             ForOfStatement: increaseComplexity,
153             IfStatement: increaseComplexity,
154             SwitchCase: increaseSwitchComplexity,
155             WhileStatement: increaseComplexity,
156             DoWhileStatement: increaseComplexity,
157
158             AssignmentExpression(node) {
159                 if (astUtils.isLogicalAssignmentOperator(node.operator)) {
160                     increaseComplexity();
161                 }
162             }
163         };
164
165     }
166 };