mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(codegen): add parenthesis in binary expression by precedence (#2067)
related ESBuild code:
f5f8ff895c/internal/js_printer/js_printer.go (L3348-L3371)
This commit is contained in:
parent
32349af691
commit
29dc5e69ff
4 changed files with 57 additions and 8 deletions
|
|
@ -1393,15 +1393,25 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for UnaryExpression<'a> {
|
|||
impl<'a, const MINIFY: bool> GenExpr<MINIFY> for BinaryExpression<'a> {
|
||||
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
|
||||
let wrap_in = self.operator == BinaryOperator::In && !ctx.has_in();
|
||||
let wrap = precedence > self.precedence() || wrap_in;
|
||||
let wrap = precedence >= self.precedence() || wrap_in;
|
||||
p.wrap(wrap, |p| {
|
||||
self.left.gen_expr(p, self.precedence(), ctx);
|
||||
let left_precedence = if self.precedence().is_right_associative() {
|
||||
self.precedence()
|
||||
} else {
|
||||
self.operator.lower_precedence()
|
||||
};
|
||||
self.left.gen_expr(p, left_precedence, ctx);
|
||||
if self.operator.is_keyword() {
|
||||
p.print_space_before_identifier();
|
||||
}
|
||||
self.operator.gen(p, ctx);
|
||||
p.print_soft_space();
|
||||
self.right.gen_expr(p, self.precedence(), ctx.union_in_if(wrap));
|
||||
let right_precedence = if self.precedence().is_left_associative() {
|
||||
self.precedence()
|
||||
} else {
|
||||
self.operator.lower_precedence()
|
||||
};
|
||||
self.right.gen_expr(p, right_precedence, ctx.union_in_if(wrap));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ fn logical_and() {
|
|||
fn bitwise_or() {
|
||||
test("a | b | c", "a|b|c;");
|
||||
test("(a | b) | c", "a|b|c;");
|
||||
test("a | (b | c)", "a|b|c;");
|
||||
test("a | (b | c)", "a|(b|c);");
|
||||
test("a | b ^ c", "a|b^c;");
|
||||
test("a | (b ^ c)", "a|b^c;");
|
||||
test("a | (b && c)", "a|(b&&c);");
|
||||
|
|
@ -124,7 +124,7 @@ fn bitwise_or() {
|
|||
fn bitwise_xor() {
|
||||
test("a ^ b ^ c", "a^b^c;");
|
||||
test("(a ^ b) ^ c", "a^b^c;");
|
||||
test("a ^ (b ^ c)", "a^b^c;");
|
||||
test("a ^ (b ^ c)", "a^(b^c);");
|
||||
test("a | b & c", "a|b&c;");
|
||||
test("a | (b & c)", "a|b&c;");
|
||||
test("a | (b || c)", "a|(b||c);");
|
||||
|
|
@ -138,7 +138,7 @@ fn bitwise_xor() {
|
|||
fn bitwise_and() {
|
||||
test("a & b & c", "a&b&c;");
|
||||
test("((a & b) & c) & d", "a&b&c&d;");
|
||||
test("a & (b & (c & d))", "a&b&c&d;");
|
||||
test("a & (b & (c & d))", "a&(b&(c&d));");
|
||||
test("a & b == c", "a&b==c;");
|
||||
test("a & (b == c)", "a&b==c;");
|
||||
test("a == b & c", "a==b&c;");
|
||||
|
|
@ -152,7 +152,7 @@ fn bitwise_and() {
|
|||
#[test]
|
||||
fn equality() {
|
||||
test("a == b != c === d !== e", "a==b!=c===d!==e;");
|
||||
test("a == (b != (c === (d !== e)))", "a==b!=c===d!==e;");
|
||||
test("a == (b != (c === (d !== e)))", "a==(b!=(c===(d!==e)));");
|
||||
test("(((a == b) != c) === d) !== e", "a==b!=c===d!==e;");
|
||||
test("a > b == c < d", "a>b==c<d;");
|
||||
test("(a > b) == (c < d)", "a>b==c<d;");
|
||||
|
|
|
|||
|
|
@ -222,6 +222,26 @@ impl BinaryOperator {
|
|||
Self::Exponential => "**",
|
||||
}
|
||||
}
|
||||
pub fn lower_precedence(&self) -> Precedence {
|
||||
match self {
|
||||
Self::BitwiseOR => Precedence::LogicalAnd,
|
||||
Self::BitwiseXOR => Precedence::BitwiseOr,
|
||||
Self::BitwiseAnd => Precedence::BitwiseXor,
|
||||
Self::Equality | Self::Inequality | Self::StrictEquality | Self::StrictInequality => {
|
||||
Precedence::BitwiseAnd
|
||||
}
|
||||
Self::LessThan
|
||||
| Self::LessEqualThan
|
||||
| Self::GreaterThan
|
||||
| Self::GreaterEqualThan
|
||||
| Self::Instanceof
|
||||
| Self::In => Precedence::Equality,
|
||||
Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill => Precedence::Relational,
|
||||
Self::Addition | Self::Subtraction => Precedence::Shift,
|
||||
Self::Multiplication | Self::Remainder | Self::Division => Precedence::Add,
|
||||
Self::Exponential => Precedence::Multiply,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetPrecedence for BinaryOperator {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,25 @@ impl Precedence {
|
|||
}
|
||||
|
||||
pub fn is_right_associative(&self) -> bool {
|
||||
matches!(self, Self::Exponential)
|
||||
matches!(self, Self::Exponential | Self::Conditional | Self::Arrow | Self::Assign)
|
||||
}
|
||||
|
||||
pub fn is_left_associative(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Member
|
||||
| Self::Multiply
|
||||
| Self::Add
|
||||
| Self::Shift
|
||||
| Self::Relational
|
||||
| Self::Equality
|
||||
| Self::BitwiseAnd
|
||||
| Self::BitwiseXor
|
||||
| Self::BitwiseOr
|
||||
| Self::LogicalAnd
|
||||
| Self::LogicalOr
|
||||
| Self::Coalesce
|
||||
| Self::Comma
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue