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