mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 02:06:08 +03:00
feat(es/lints): Implement no-compare-neg-zero
rule (#4643)
This commit is contained in:
parent
0b35b047bf
commit
f45dd72033
@ -0,0 +1,9 @@
|
||||
{
|
||||
"jsc": {
|
||||
"lints": {
|
||||
"no-compare-neg-zero": [
|
||||
"error"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
x === -0;
|
||||
-0 === x;
|
||||
x == -0;
|
||||
-0 == x;
|
||||
x > -0;
|
||||
-0 > x;
|
||||
x >= -0;
|
||||
-0 >= x;
|
||||
x < -0;
|
||||
-0 < x;
|
||||
x <= -0;
|
||||
-0 <= x;
|
||||
-0 === -0
|
||||
|
||||
x == '-0'
|
||||
Object.is(x, -0)
|
@ -0,0 +1,78 @@
|
||||
|
||||
x Do not use the '===' to compare against -0
|
||||
,----
|
||||
1 | x === -0;
|
||||
: ^^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '===' to compare against -0
|
||||
,----
|
||||
2 | -0 === x;
|
||||
: ^^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '==' to compare against -0
|
||||
,----
|
||||
3 | x == -0;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '==' to compare against -0
|
||||
,----
|
||||
4 | -0 == x;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '>' to compare against -0
|
||||
,----
|
||||
5 | x > -0;
|
||||
: ^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '>' to compare against -0
|
||||
,----
|
||||
6 | -0 > x;
|
||||
: ^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '>=' to compare against -0
|
||||
,----
|
||||
7 | x >= -0;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '>=' to compare against -0
|
||||
,----
|
||||
8 | -0 >= x;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '<' to compare against -0
|
||||
,----
|
||||
9 | x < -0;
|
||||
: ^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '<' to compare against -0
|
||||
,----
|
||||
10 | -0 < x;
|
||||
: ^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '<=' to compare against -0
|
||||
,----
|
||||
11 | x <= -0;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '<=' to compare against -0
|
||||
,----
|
||||
12 | -0 <= x;
|
||||
: ^^^^^^^
|
||||
`----
|
||||
|
||||
x Do not use the '===' to compare against -0
|
||||
,----
|
||||
13 | -0 === -0
|
||||
: ^^^^^^^^^
|
||||
`----
|
@ -191,4 +191,8 @@ pub struct LintConfig {
|
||||
#[cfg(feature = "non_critical_lints")]
|
||||
#[serde(default, alias = "preferConst")]
|
||||
pub prefer_const: RuleConfig<()>,
|
||||
|
||||
#[cfg(feature = "non_critical_lints")]
|
||||
#[serde(default, alias = "noCompareNegZero")]
|
||||
pub no_compare_neg_zero: RuleConfig<()>,
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ pub(crate) mod non_critical_lints {
|
||||
pub mod eqeqeq;
|
||||
pub mod no_alert;
|
||||
pub mod no_bitwise;
|
||||
pub mod no_compare_neg_zero;
|
||||
pub mod no_console;
|
||||
pub mod no_debugger;
|
||||
pub mod no_empty_function;
|
||||
@ -166,6 +167,10 @@ pub fn all(lint_params: LintParams) -> Vec<Box<dyn Rule>> {
|
||||
rules.extend(no_var::no_var(&lint_config.no_var));
|
||||
|
||||
rules.extend(prefer_const::prefer_const(&lint_config.prefer_const));
|
||||
|
||||
rules.extend(no_compare_neg_zero::no_compare_neg_zero(
|
||||
&lint_config.no_compare_neg_zero,
|
||||
));
|
||||
}
|
||||
|
||||
rules
|
||||
|
84
crates/swc_ecma_lints/src/rules/no_compare_neg_zero.rs
Normal file
84
crates/swc_ecma_lints/src/rules/no_compare_neg_zero.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use swc_common::{errors::HANDLER, Span};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_visit::{Visit, VisitWith};
|
||||
|
||||
use crate::{
|
||||
config::{LintRuleReaction, RuleConfig},
|
||||
rule::{visitor_rule, Rule},
|
||||
rules::utils::unwrap_seqs_and_parens,
|
||||
};
|
||||
|
||||
pub fn no_compare_neg_zero(config: &RuleConfig<()>) -> Option<Box<dyn Rule>> {
|
||||
let rule_reaction = config.get_rule_reaction();
|
||||
|
||||
match rule_reaction {
|
||||
LintRuleReaction::Off => None,
|
||||
_ => Some(visitor_rule(NoCompareNegZero::new(rule_reaction))),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct NoCompareNegZero {
|
||||
expected_reaction: LintRuleReaction,
|
||||
}
|
||||
|
||||
impl NoCompareNegZero {
|
||||
fn new(expected_reaction: LintRuleReaction) -> Self {
|
||||
Self { expected_reaction }
|
||||
}
|
||||
|
||||
fn emit_report(&self, op: BinaryOp, span: Span) {
|
||||
let message = format!("Do not use the '{}' to compare against -0", op);
|
||||
|
||||
HANDLER.with(|handler| match self.expected_reaction {
|
||||
LintRuleReaction::Error => {
|
||||
handler.struct_span_err(span, &message).emit();
|
||||
}
|
||||
LintRuleReaction::Warning => {
|
||||
handler.struct_span_warn(span, &message).emit();
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
|
||||
fn is_neg_zero(&self, expr: &Expr) -> bool {
|
||||
if let Expr::Unary(UnaryExpr {
|
||||
op: op!(unary, "-"),
|
||||
arg,
|
||||
..
|
||||
}) = unwrap_seqs_and_parens(expr)
|
||||
{
|
||||
if let Expr::Lit(Lit::Num(Number { value, .. })) = unwrap_seqs_and_parens(arg.as_ref())
|
||||
{
|
||||
return *value == 0f64;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn check(&self, bin_expr: &BinExpr) {
|
||||
if let op!("===")
|
||||
| op!("==")
|
||||
| op!("!==")
|
||||
| op!("!=")
|
||||
| op!("<")
|
||||
| op!("<=")
|
||||
| op!(">")
|
||||
| op!(">=") = bin_expr.op
|
||||
{
|
||||
if self.is_neg_zero(bin_expr.left.as_ref()) || self.is_neg_zero(bin_expr.right.as_ref())
|
||||
{
|
||||
self.emit_report(bin_expr.op, bin_expr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for NoCompareNegZero {
|
||||
fn visit_bin_expr(&mut self, bin_expr: &BinExpr) {
|
||||
self.check(bin_expr);
|
||||
|
||||
bin_expr.visit_children_with(self);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user