massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / use-isnan.js
1 /**
2  * @fileoverview Rule to flag comparisons to the value NaN
3  * @author James Allardice
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Helpers
16 //------------------------------------------------------------------------------
17
18 /**
19  * Determines if the given node is a NaN `Identifier` node.
20  * @param {ASTNode|null} node The node to check.
21  * @returns {boolean} `true` if the node is 'NaN' identifier.
22  */
23 function isNaNIdentifier(node) {
24     return Boolean(node) && (
25         astUtils.isSpecificId(node, "NaN") ||
26         astUtils.isSpecificMemberAccess(node, "Number", "NaN")
27     );
28 }
29
30 //------------------------------------------------------------------------------
31 // Rule Definition
32 //------------------------------------------------------------------------------
33
34 module.exports = {
35     meta: {
36         type: "problem",
37
38         docs: {
39             description: "require calls to `isNaN()` when checking for `NaN`",
40             category: "Possible Errors",
41             recommended: true,
42             url: "https://eslint.org/docs/rules/use-isnan"
43         },
44
45         schema: [
46             {
47                 type: "object",
48                 properties: {
49                     enforceForSwitchCase: {
50                         type: "boolean",
51                         default: true
52                     },
53                     enforceForIndexOf: {
54                         type: "boolean",
55                         default: false
56                     }
57                 },
58                 additionalProperties: false
59             }
60         ],
61
62         messages: {
63             comparisonWithNaN: "Use the isNaN function to compare with NaN.",
64             switchNaN: "'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch.",
65             caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch.",
66             indexOfNaN: "Array prototype method '{{ methodName }}' cannot find NaN."
67         }
68     },
69
70     create(context) {
71
72         const enforceForSwitchCase = !context.options[0] || context.options[0].enforceForSwitchCase;
73         const enforceForIndexOf = context.options[0] && context.options[0].enforceForIndexOf;
74
75         /**
76          * Checks the given `BinaryExpression` node for `foo === NaN` and other comparisons.
77          * @param {ASTNode} node The node to check.
78          * @returns {void}
79          */
80         function checkBinaryExpression(node) {
81             if (
82                 /^(?:[<>]|[!=]=)=?$/u.test(node.operator) &&
83                 (isNaNIdentifier(node.left) || isNaNIdentifier(node.right))
84             ) {
85                 context.report({ node, messageId: "comparisonWithNaN" });
86             }
87         }
88
89         /**
90          * Checks the discriminant and all case clauses of the given `SwitchStatement` node for `switch(NaN)` and `case NaN:`
91          * @param {ASTNode} node The node to check.
92          * @returns {void}
93          */
94         function checkSwitchStatement(node) {
95             if (isNaNIdentifier(node.discriminant)) {
96                 context.report({ node, messageId: "switchNaN" });
97             }
98
99             for (const switchCase of node.cases) {
100                 if (isNaNIdentifier(switchCase.test)) {
101                     context.report({ node: switchCase, messageId: "caseNaN" });
102                 }
103             }
104         }
105
106         /**
107          * Checks the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
108          * @param {ASTNode} node The node to check.
109          * @returns {void}
110          */
111         function checkCallExpression(node) {
112             const callee = astUtils.skipChainExpression(node.callee);
113
114             if (callee.type === "MemberExpression") {
115                 const methodName = astUtils.getStaticPropertyName(callee);
116
117                 if (
118                     (methodName === "indexOf" || methodName === "lastIndexOf") &&
119                     node.arguments.length === 1 &&
120                     isNaNIdentifier(node.arguments[0])
121                 ) {
122                     context.report({ node, messageId: "indexOfNaN", data: { methodName } });
123                 }
124             }
125         }
126
127         const listeners = {
128             BinaryExpression: checkBinaryExpression
129         };
130
131         if (enforceForSwitchCase) {
132             listeners.SwitchStatement = checkSwitchStatement;
133         }
134
135         if (enforceForIndexOf) {
136             listeners.CallExpression = checkCallExpression;
137         }
138
139         return listeners;
140     }
141 };