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