55
66"use strict" ;
77
8+ //------------------------------------------------------------------------------
9+ // Helpers
10+ //------------------------------------------------------------------------------
11+
12+ /**
13+ * Determines if the given node is a NaN `Identifier` node.
14+ *@param {ASTNode|null } node The node to check.
15+ *@returns {boolean } `true` if the node is 'NaN' identifier.
16+ */
17+ function isNaNIdentifier ( node ) {
18+ return Boolean ( node ) && node . type === "Identifier" && node . name === "NaN" ;
19+ }
20+
821//------------------------------------------------------------------------------
922// Rule Definition
1023//------------------------------------------------------------------------------
@@ -20,21 +33,69 @@ module.exports = {
2033url :"https://eslint.org/docs/rules/use-isnan"
2134} ,
2235
23- schema :[ ] ,
36+ schema :[
37+ {
38+ type :"object" ,
39+ properties :{
40+ enforceForSwitchCase :{
41+ type :"boolean" ,
42+ default :false
43+ }
44+ } ,
45+ additionalProperties :false
46+ }
47+ ] ,
48+
2449messages :{
25- useIsNaN :"Use the isNaN function to compare with NaN."
50+ comparisonWithNaN :"Use the isNaN function to compare with NaN." ,
51+ switchNaN :"'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch." ,
52+ caseNaN :"'case NaN' can never match. Use Number.isNaN before the switch."
2653}
2754} ,
2855
2956create ( context ) {
3057
31- return {
32- BinaryExpression ( node ) {
33- if ( / ^ (?: [ < > ] | [ ! = ] = ) = ? $ / u. test ( node . operator ) && ( node . left . name === "NaN" || node . right . name === "NaN" ) ) {
34- context . report ( { node, messageId :"useIsNaN" } ) ;
58+ const enforceForSwitchCase = context . options [ 0 ] && context . options [ 0 ] . enforceForSwitchCase ;
59+
60+ /**
61+ * Checks the given `BinaryExpression` node.
62+ *@param {ASTNode } node The node to check.
63+ *@returns {void }
64+ */
65+ function checkBinaryExpression ( node ) {
66+ if (
67+ / ^ (?: [ < > ] | [ ! = ] = ) = ? $ / u. test ( node . operator ) &&
68+ ( isNaNIdentifier ( node . left ) || isNaNIdentifier ( node . right ) )
69+ ) {
70+ context . report ( { node, messageId :"comparisonWithNaN" } ) ;
71+ }
72+ }
73+
74+ /**
75+ * Checks the discriminant and all case clauses of the given `SwitchStatement` node.
76+ *@param {ASTNode } node The node to check.
77+ *@returns {void }
78+ */
79+ function checkSwitchStatement ( node ) {
80+ if ( isNaNIdentifier ( node . discriminant ) ) {
81+ context . report ( { node, messageId :"switchNaN" } ) ;
82+ }
83+
84+ for ( const switchCase of node . cases ) {
85+ if ( isNaNIdentifier ( switchCase . test ) ) {
86+ context . report ( { node :switchCase , messageId :"caseNaN" } ) ;
3587}
3688}
89+ }
90+
91+ const listeners = {
92+ BinaryExpression :checkBinaryExpression
3793} ;
3894
95+ if ( enforceForSwitchCase ) {
96+ listeners . SwitchStatement = checkSwitchStatement ;
97+ }
98+
99+ return listeners ;
39100}
40101} ;