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