From 2f6c3b9cec00e3ae13b1c30532b1ee56e64c8cf5 Mon Sep 17 00:00:00 2001 From: heygsc <1596920983@qq.com> Date: Thu, 8 Aug 2024 17:12:02 +0800 Subject: [PATCH] feat(linter): add fixer for eslint/no-compare-neg-zero (#4748) part of #4179 --------- Co-authored-by: wenzhe --- .../src/rules/eslint/no_compare_neg_zero.rs | 60 +++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_compare_neg_zero.rs b/crates/oxc_linter/src/rules/eslint/no_compare_neg_zero.rs index 2c99118a27ae2..1575f8c79b5a6 100644 --- a/crates/oxc_linter/src/rules/eslint/no_compare_neg_zero.rs +++ b/crates/oxc_linter/src/rules/eslint/no_compare_neg_zero.rs @@ -1,7 +1,7 @@ use oxc_ast::{ast::Expression, AstKind}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{GetSpan, Span}; use oxc_syntax::operator::{BinaryOperator, UnaryOperator}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -29,7 +29,8 @@ declare_oxc_lint!( /// if (x === -0) {} /// ``` NoCompareNegZero, - correctness + correctness, + conditional_suggestion_fix ); impl Rule for NoCompareNegZero { @@ -39,8 +40,41 @@ impl Rule for NoCompareNegZero { }; if Self::should_check(expr.operator) { let op = expr.operator.as_str(); - if is_neg_zero(&expr.left) || is_neg_zero(&expr.right) { - ctx.diagnostic(no_compare_neg_zero_diagnostic(op, expr.span)); + let is_left_neg_zero = is_neg_zero(&expr.left); + let is_right_neg_zero = is_neg_zero(&expr.right); + if is_left_neg_zero || is_right_neg_zero { + if expr.operator == BinaryOperator::StrictEquality { + ctx.diagnostic_with_suggestion( + no_compare_neg_zero_diagnostic(op, expr.span), + |fixer| { + // replace `x === -0` with `Object.is(x, -0)` + let value = if is_left_neg_zero { + ctx.source_range(expr.right.span()) + } else { + ctx.source_range(expr.left.span()) + }; + fixer.replace(expr.span, format!("Object.is({value}, -0)")) + }, + ); + } else { + // + // + // The mathematical value of +0𝔽 and -0𝔽 is the mathematical value 0. + // It's safe to replace -0 with 0 + ctx.diagnostic_with_fix( + no_compare_neg_zero_diagnostic(op, expr.span), + |fixer| { + let start = if is_left_neg_zero { + expr.left.span().start + } else { + expr.right.span().start + }; + let end = start + 1; + let span = Span::new(start, end); + fixer.delete(&span) + }, + ); + } } } } @@ -117,5 +151,21 @@ fn test() { ("-0n <= x", None), ]; - Tester::new(NoCompareNegZero::NAME, pass, fail).test_and_snapshot(); + let fix = vec![ + ("x === -0", "Object.is(x, -0)", None), + ("-0 === x", "Object.is(x, -0)", None), + ("x == -0", "x == 0", None), + ("-0 == x", "0 == x", None), + ("x > -0", "x > 0", None), + ("-0 > x", "0 > x", None), + ("x >= -0", "x >= 0", None), + ("-0 >= x", "0 >= x", None), + ("x < -0", "x < 0", None), + ("-0 < x", "0 < x", None), + ("x <= -0", "x <= 0", None), + ("-0 <= x", "0 <= x", None), + ("-0n <= x", "0n <= x", None), + ]; + + Tester::new(NoCompareNegZero::NAME, pass, fail).expect_fix(fix).test_and_snapshot(); }