@@ -20,7 +20,7 @@ const astUtils = require("./utils/ast-utils");
20
20
* @returns {boolean } Whether or not it is a comparison operator.
21
21
*/
22
22
function isComparisonOperator ( operator ) {
23
- return ( / ^ ( = = | = = = | ! = | ! = = | < | > | < = | > = ) $ / u) . test ( operator ) ;
23
+ return / ^ ( = = | = = = | ! = | ! = = | < | > | < = | > = ) $ / u. test ( operator ) ;
24
24
}
25
25
26
26
/**
@@ -29,7 +29,7 @@ function isComparisonOperator(operator) {
29
29
* @returns {boolean } Whether or not it is an equality operator.
30
30
*/
31
31
function isEqualityOperator ( operator ) {
32
- return ( / ^ ( = = | = = = ) $ / u) . test ( operator ) ;
32
+ return / ^ ( = = | = = = ) $ / u. test ( operator ) ;
33
33
}
34
34
35
35
/**
@@ -50,10 +50,12 @@ function isRangeTestOperator(operator) {
50
50
* real literal and should be treated as such.
51
51
*/
52
52
function isNegativeNumericLiteral ( node ) {
53
- return ( node . type === "UnaryExpression" &&
53
+ return (
54
+ node . type === "UnaryExpression" &&
54
55
node . operator === "-" &&
55
56
node . prefix &&
56
- astUtils . isNumericLiteral ( node . argument ) ) ;
57
+ astUtils . isNumericLiteral ( node . argument )
58
+ ) ;
57
59
}
58
60
59
61
/**
@@ -71,25 +73,21 @@ function isStaticTemplateLiteral(node) {
71
73
* @returns {boolean } True if the node should be treated as a single Literal node.
72
74
*/
73
75
function looksLikeLiteral ( node ) {
74
- return isNegativeNumericLiteral ( node ) ||
75
- isStaticTemplateLiteral ( node ) ;
76
+ return isNegativeNumericLiteral ( node ) || isStaticTemplateLiteral ( node ) ;
76
77
}
77
78
78
79
/**
79
80
* Attempts to derive a Literal node from nodes that are treated like literals.
80
81
* @param {ASTNode } node Node to normalize.
81
- * @param {number } [defaultValue] The default value to be returned if the node
82
- * is not a Literal.
83
82
* @returns {ASTNode } One of the following options.
84
83
* 1. The original node if the node is already a Literal
85
84
* 2. A normalized Literal node with the negative number as the value if the
86
85
* node represents a negative number literal.
87
86
* 3. A normalized Literal node with the string as the value if the node is
88
87
* a Template Literal without expression.
89
- * 4. The Literal node which has the `defaultValue` argument if it exists.
90
- * 5. Otherwise `null`.
88
+ * 4. Otherwise `null`.
91
89
*/
92
- function getNormalizedLiteral ( node , defaultValue ) {
90
+ function getNormalizedLiteral ( node ) {
93
91
if ( node . type === "Literal" ) {
94
92
return node ;
95
93
}
@@ -110,14 +108,6 @@ function getNormalizedLiteral(node, defaultValue) {
110
108
} ;
111
109
}
112
110
113
- if ( defaultValue ) {
114
- return {
115
- type : "Literal" ,
116
- value : defaultValue ,
117
- raw : String ( defaultValue )
118
- } ;
119
- }
120
-
121
111
return null ;
122
112
}
123
113
@@ -183,7 +173,7 @@ module.exports = {
183
173
type : "suggestion" ,
184
174
185
175
docs : {
186
- description : " require or disallow \ "Yoda\ " conditions" ,
176
+ description : ' require or disallow "Yoda" conditions' ,
187
177
category : "Best Practices" ,
188
178
recommended : false ,
189
179
url : "https://eslint.org/docs/rules/yoda"
@@ -211,16 +201,19 @@ module.exports = {
211
201
212
202
fixable : "code" ,
213
203
messages : {
214
- expected : "Expected literal to be on the {{expectedSide}} side of {{operator}}."
204
+ expected :
205
+ "Expected literal to be on the {{expectedSide}} side of {{operator}}."
215
206
}
216
207
} ,
217
208
218
209
create ( context ) {
219
210
220
211
// Default to "never" (!always) if no option
221
- const always = ( context . options [ 0 ] === "always" ) ;
222
- const exceptRange = ( context . options [ 1 ] && context . options [ 1 ] . exceptRange ) ;
223
- const onlyEquality = ( context . options [ 1 ] && context . options [ 1 ] . onlyEquality ) ;
212
+ const always = context . options [ 0 ] === "always" ;
213
+ const exceptRange =
214
+ context . options [ 1 ] && context . options [ 1 ] . exceptRange ;
215
+ const onlyEquality =
216
+ context . options [ 1 ] && context . options [ 1 ] . onlyEquality ;
224
217
225
218
const sourceCode = context . getSourceCode ( ) ;
226
219
@@ -243,27 +236,48 @@ module.exports = {
243
236
* @returns {boolean } Whether node is a "between" range test.
244
237
*/
245
238
function isBetweenTest ( ) {
246
- let leftLiteral , rightLiteral ;
239
+ if ( node . operator === "&&" && same ( left . right , right . left ) ) {
240
+ const leftLiteral = getNormalizedLiteral ( left . left ) ;
241
+ const rightLiteral = getNormalizedLiteral ( right . right ) ;
242
+
243
+ if ( leftLiteral === null && rightLiteral === null ) {
244
+ return false ;
245
+ }
247
246
248
- return ( node . operator === "&&" &&
249
- ( leftLiteral = getNormalizedLiteral ( left . left ) ) &&
250
- ( rightLiteral = getNormalizedLiteral ( right . right , Number . POSITIVE_INFINITY ) ) &&
251
- leftLiteral . value <= rightLiteral . value &&
252
- same ( left . right , right . left ) ) ;
247
+ if ( rightLiteral === null || leftLiteral === null ) {
248
+ return true ;
249
+ }
250
+
251
+ if ( leftLiteral . value <= rightLiteral . value ) {
252
+ return true ;
253
+ }
254
+ }
255
+ return false ;
253
256
}
254
257
255
258
/**
256
259
* Determines whether node is of the form `x < 0 || 1 <= x`.
257
260
* @returns {boolean } Whether node is an "outside" range test.
258
261
*/
259
262
function isOutsideTest ( ) {
260
- let leftLiteral , rightLiteral ;
263
+ if ( node . operator === "||" && same ( left . left , right . right ) ) {
264
+ const leftLiteral = getNormalizedLiteral ( left . right ) ;
265
+ const rightLiteral = getNormalizedLiteral ( right . left ) ;
266
+
267
+ if ( leftLiteral === null && rightLiteral === null ) {
268
+ return false ;
269
+ }
270
+
271
+ if ( rightLiteral === null || leftLiteral === null ) {
272
+ return true ;
273
+ }
274
+
275
+ if ( leftLiteral . value <= rightLiteral . value ) {
276
+ return true ;
277
+ }
278
+ }
261
279
262
- return ( node . operator === "||" &&
263
- ( leftLiteral = getNormalizedLiteral ( left . right , Number . NEGATIVE_INFINITY ) ) &&
264
- ( rightLiteral = getNormalizedLiteral ( right . left ) ) &&
265
- leftLiteral . value <= rightLiteral . value &&
266
- same ( left . left , right . right ) ) ;
280
+ return false ;
267
281
}
268
282
269
283
/**
@@ -276,13 +290,15 @@ module.exports = {
276
290
return astUtils . isParenthesised ( sourceCode , node ) ;
277
291
}
278
292
279
- return ( node . type === "LogicalExpression" &&
293
+ return (
294
+ node . type === "LogicalExpression" &&
280
295
left . type === "BinaryExpression" &&
281
296
right . type === "BinaryExpression" &&
282
297
isRangeTestOperator ( left . operator ) &&
283
298
isRangeTestOperator ( right . operator ) &&
284
299
( isBetweenTest ( ) || isOutsideTest ( ) ) &&
285
- isParenWrapped ( ) ) ;
300
+ isParenWrapped ( )
301
+ ) ;
286
302
}
287
303
288
304
const OPERATOR_FLIP_MAP = {
@@ -303,21 +319,52 @@ module.exports = {
303
319
*/
304
320
function getFlippedString ( node ) {
305
321
const tokenBefore = sourceCode . getTokenBefore ( node ) ;
306
- const operatorToken = sourceCode . getFirstTokenBetween ( node . left , node . right , token => token . value === node . operator ) ;
307
- const textBeforeOperator = sourceCode . getText ( ) . slice ( sourceCode . getTokenBefore ( operatorToken ) . range [ 1 ] , operatorToken . range [ 0 ] ) ;
308
- const textAfterOperator = sourceCode . getText ( ) . slice ( operatorToken . range [ 1 ] , sourceCode . getTokenAfter ( operatorToken ) . range [ 0 ] ) ;
309
- const leftText = sourceCode . getText ( ) . slice ( node . range [ 0 ] , sourceCode . getTokenBefore ( operatorToken ) . range [ 1 ] ) ;
322
+ const operatorToken = sourceCode . getFirstTokenBetween (
323
+ node . left ,
324
+ node . right ,
325
+ token => token . value === node . operator
326
+ ) ;
327
+ const textBeforeOperator = sourceCode
328
+ . getText ( )
329
+ . slice (
330
+ sourceCode . getTokenBefore ( operatorToken ) . range [ 1 ] ,
331
+ operatorToken . range [ 0 ]
332
+ ) ;
333
+ const textAfterOperator = sourceCode
334
+ . getText ( )
335
+ . slice (
336
+ operatorToken . range [ 1 ] ,
337
+ sourceCode . getTokenAfter ( operatorToken ) . range [ 0 ]
338
+ ) ;
339
+ const leftText = sourceCode
340
+ . getText ( )
341
+ . slice (
342
+ node . range [ 0 ] ,
343
+ sourceCode . getTokenBefore ( operatorToken ) . range [ 1 ]
344
+ ) ;
310
345
const firstRightToken = sourceCode . getTokenAfter ( operatorToken ) ;
311
- const rightText = sourceCode . getText ( ) . slice ( firstRightToken . range [ 0 ] , node . range [ 1 ] ) ;
346
+ const rightText = sourceCode
347
+ . getText ( )
348
+ . slice ( firstRightToken . range [ 0 ] , node . range [ 1 ] ) ;
312
349
313
350
let prefix = "" ;
314
351
315
- if ( tokenBefore && tokenBefore . range [ 1 ] === node . range [ 0 ] &&
316
- ! astUtils . canTokensBeAdjacent ( tokenBefore , firstRightToken ) ) {
352
+ if (
353
+ tokenBefore &&
354
+ tokenBefore . range [ 1 ] === node . range [ 0 ] &&
355
+ ! astUtils . canTokensBeAdjacent ( tokenBefore , firstRightToken )
356
+ ) {
317
357
prefix = " " ;
318
358
}
319
359
320
- return prefix + rightText + textBeforeOperator + OPERATOR_FLIP_MAP [ operatorToken . value ] + textAfterOperator + leftText ;
360
+ return (
361
+ prefix +
362
+ rightText +
363
+ textBeforeOperator +
364
+ OPERATOR_FLIP_MAP [ operatorToken . value ] +
365
+ textAfterOperator +
366
+ leftText
367
+ ) ;
321
368
}
322
369
323
370
//--------------------------------------------------------------------------
@@ -331,8 +378,12 @@ module.exports = {
331
378
332
379
// If `expectedLiteral` is not a literal, and `expectedNonLiteral` is a literal, raise an error.
333
380
if (
334
- ( expectedNonLiteral . type === "Literal" || looksLikeLiteral ( expectedNonLiteral ) ) &&
335
- ! ( expectedLiteral . type === "Literal" || looksLikeLiteral ( expectedLiteral ) ) &&
381
+ ( expectedNonLiteral . type === "Literal" ||
382
+ looksLikeLiteral ( expectedNonLiteral ) ) &&
383
+ ! (
384
+ expectedLiteral . type === "Literal" ||
385
+ looksLikeLiteral ( expectedLiteral )
386
+ ) &&
336
387
! ( ! isEqualityOperator ( node . operator ) && onlyEquality ) &&
337
388
isComparisonOperator ( node . operator ) &&
338
389
! ( exceptRange && isRangeTest ( context . getAncestors ( ) . pop ( ) ) )
@@ -344,12 +395,11 @@ module.exports = {
344
395
operator : node . operator ,
345
396
expectedSide : always ? "left" : "right"
346
397
} ,
347
- fix : fixer => fixer . replaceText ( node , getFlippedString ( node ) )
398
+ fix : fixer =>
399
+ fixer . replaceText ( node , getFlippedString ( node ) )
348
400
} ) ;
349
401
}
350
-
351
402
}
352
403
} ;
353
-
354
404
}
355
405
} ;
0 commit comments