fix(es/fixer): Remove needless parens for nested ?? (#5432)

This commit is contained in:
Austaras 2022-08-10 16:26:33 +08:00 committed by GitHub
parent b589f2b771
commit e35990390b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 12 deletions

View File

@ -104,6 +104,10 @@ impl BinaryOp {
BinaryOp::NullishCoalescing => 1,
}
}
pub fn may_short_circuit(&self) -> bool {
matches!(self, op!("??") | op!("||") | op!("&&"))
}
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]

View File

@ -255,14 +255,10 @@ impl VisitMut for Fixer<'_> {
}
Expr::Bin(BinExpr { op: op_of_rhs, .. }) => {
if *op_of_rhs == expr.op {
match expr.op {
// `a && (b && c)` == `a && b && c`
// `a || (b || c)` == `a || b || c`
// `a ** (b ** c)` == `a ** b ** c`
op!("&&") | op!("||") | op!("**") => {}
_ => {
self.wrap(&mut expr.right);
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#precedence_and_associativity
// `**` is the only right associative operator in js
if !(expr.op.may_short_circuit() || expr.op == op!("**")) {
self.wrap(&mut expr.right);
}
} else if op_of_rhs.precedence() <= expr.op.precedence()
|| (*op_of_rhs == op!("&&") && expr.op == op!("??"))
@ -274,7 +270,7 @@ impl VisitMut for Fixer<'_> {
};
match &mut *expr.left {
Expr::Bin(BinExpr { op: op!("??"), .. }) => {
Expr::Bin(BinExpr { op: op!("??"), .. }) if expr.op != op!("??") => {
self.wrap(&mut expr.left);
}
@ -321,8 +317,11 @@ impl VisitMut for Fixer<'_> {
}
if let op!("??") = expr.op {
if let Expr::Bin(..) = &mut *expr.left {
self.wrap(&mut expr.left);
match &*expr.left {
Expr::Bin(BinExpr { op, .. }) if *op != op!("??") => {
self.wrap(&mut expr.left);
}
_ => (),
}
}
}
@ -1641,5 +1640,7 @@ var store = global[SHARED] || (global[SHARED] = {});
"
);
identical!(issue_5417, "console.log(a ?? b ?? c)");
identical!(bin_and_unary, "console.log(a++ && b--)");
}

View File

@ -1430,7 +1430,7 @@ fn ignore_result(e: Expr, drop_str_lit: bool, ctx: &ExprCtx) -> Option<Expr> {
left,
op,
right,
}) if op != op!("&&") && op != op!("||") && op != op!("??") => {
}) if !op.may_short_circuit() => {
let left = ignore_result(*left, true, ctx);
let right = ignore_result(*right, true, ctx);