1
1
use oxc_ast:: { ast:: Expression , AstKind } ;
2
2
use oxc_diagnostics:: OxcDiagnostic ;
3
3
use oxc_macros:: declare_oxc_lint;
4
- use oxc_span:: Span ;
4
+ use oxc_span:: { GetSpan , Span } ;
5
5
use oxc_syntax:: operator:: { BinaryOperator , UnaryOperator } ;
6
6
7
7
use crate :: { context:: LintContext , rule:: Rule , AstNode } ;
@@ -29,7 +29,8 @@ declare_oxc_lint!(
29
29
/// if (x === -0) {}
30
30
/// ```
31
31
NoCompareNegZero ,
32
- correctness
32
+ correctness,
33
+ conditional_suggestion_fix
33
34
) ;
34
35
35
36
impl Rule for NoCompareNegZero {
@@ -39,8 +40,41 @@ impl Rule for NoCompareNegZero {
39
40
} ;
40
41
if Self :: should_check ( expr. operator ) {
41
42
let op = expr. operator . as_str ( ) ;
42
- if is_neg_zero ( & expr. left ) || is_neg_zero ( & expr. right ) {
43
- ctx. diagnostic ( no_compare_neg_zero_diagnostic ( op, expr. span ) ) ;
43
+ let is_left_neg_zero = is_neg_zero ( & expr. left ) ;
44
+ let is_right_neg_zero = is_neg_zero ( & expr. right ) ;
45
+ if is_left_neg_zero || is_right_neg_zero {
46
+ if expr. operator == BinaryOperator :: StrictEquality {
47
+ ctx. diagnostic_with_suggestion (
48
+ no_compare_neg_zero_diagnostic ( op, expr. span ) ,
49
+ |fixer| {
50
+ // replace `x === -0` with `Object.is(x, -0)`
51
+ let value = if is_left_neg_zero {
52
+ ctx. source_range ( expr. right . span ( ) )
53
+ } else {
54
+ ctx. source_range ( expr. left . span ( ) )
55
+ } ;
56
+ fixer. replace ( expr. span , format ! ( "Object.is({value}, -0)" ) )
57
+ } ,
58
+ ) ;
59
+ } else {
60
+ // <https://tc39.es/ecma262/#%E2%84%9D>
61
+ // <https://tc39.es/ecma262/#sec-numeric-types-number-lessThan>
62
+ // The mathematical value of +0𝔽 and -0𝔽 is the mathematical value 0.
63
+ // It's safe to replace -0 with 0
64
+ ctx. diagnostic_with_fix (
65
+ no_compare_neg_zero_diagnostic ( op, expr. span ) ,
66
+ |fixer| {
67
+ let start = if is_left_neg_zero {
68
+ expr. left . span ( ) . start
69
+ } else {
70
+ expr. right . span ( ) . start
71
+ } ;
72
+ let end = start + 1 ;
73
+ let span = Span :: new ( start, end) ;
74
+ fixer. delete ( & span)
75
+ } ,
76
+ ) ;
77
+ }
44
78
}
45
79
}
46
80
}
@@ -117,5 +151,21 @@ fn test() {
117
151
( "-0n <= x" , None ) ,
118
152
] ;
119
153
120
- Tester :: new ( NoCompareNegZero :: NAME , pass, fail) . test_and_snapshot ( ) ;
154
+ let fix = vec ! [
155
+ ( "x === -0" , "Object.is(x, -0)" , None ) ,
156
+ ( "-0 === x" , "Object.is(x, -0)" , None ) ,
157
+ ( "x == -0" , "x == 0" , None ) ,
158
+ ( "-0 == x" , "0 == x" , None ) ,
159
+ ( "x > -0" , "x > 0" , None ) ,
160
+ ( "-0 > x" , "0 > x" , None ) ,
161
+ ( "x >= -0" , "x >= 0" , None ) ,
162
+ ( "-0 >= x" , "0 >= x" , None ) ,
163
+ ( "x < -0" , "x < 0" , None ) ,
164
+ ( "-0 < x" , "0 < x" , None ) ,
165
+ ( "x <= -0" , "x <= 0" , None ) ,
166
+ ( "-0 <= x" , "0 <= x" , None ) ,
167
+ ( "-0n <= x" , "0n <= x" , None ) ,
168
+ ] ;
169
+
170
+ Tester :: new ( NoCompareNegZero :: NAME , pass, fail) . expect_fix ( fix) . test_and_snapshot ( ) ;
121
171
}
0 commit comments