diff --git a/compiler/fmt/src/expr.rs b/compiler/fmt/src/expr.rs index 9160188699..b2a58df133 100644 --- a/compiler/fmt/src/expr.rs +++ b/compiler/fmt/src/expr.rs @@ -133,7 +133,7 @@ impl<'a> Formattable<'a> for Expr<'a> { } } ParensAround(sub_expr) => { - if parens == Parens::NotNeeded { + if parens == Parens::NotNeeded && !sub_expr_requests_parens(&sub_expr) { sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent); } else { buf.push('('); @@ -319,7 +319,7 @@ impl<'a> Formattable<'a> for Expr<'a> { buf.push_str(key); } Access(expr, key) => { - expr.format_with_options(buf, parens, Newlines::Yes, indent); + expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent); buf.push('.'); buf.push_str(key); } @@ -398,6 +398,8 @@ fn fmt_bin_ops<'a>( || lefts.iter().any(|(expr, _)| expr.value.is_multiline()); for (loc_left_side, loc_bin_op) in lefts { + let bin_op = loc_bin_op.value; + loc_left_side.format_with_options(buf, apply_needs_parens, Newlines::No, indent); if is_multiline { @@ -406,7 +408,7 @@ fn fmt_bin_ops<'a>( buf.push(' '); } - push_op(buf, loc_bin_op.value); + push_op(buf, bin_op); buf.push(' '); } @@ -1050,3 +1052,32 @@ fn format_field_multiline<'a, T>( } } } + +fn sub_expr_requests_parens(expr: &Expr<'_>) -> bool { + match expr { + Expr::BinOps(left_side, _) => { + left_side + .iter() + .any(|(_, loc_bin_op)| match loc_bin_op.value { + BinOp::Caret + | BinOp::Star + | BinOp::Slash + | BinOp::DoubleSlash + | BinOp::Percent + | BinOp::DoublePercent + | BinOp::Plus + | BinOp::Minus + | BinOp::Equals + | BinOp::NotEquals + | BinOp::LessThan + | BinOp::GreaterThan + | BinOp::LessThanOrEq + | BinOp::GreaterThanOrEq + | BinOp::And + | BinOp::Or => true, + BinOp::Pizza | BinOp::Assignment | BinOp::HasType | BinOp::Backpassing => false, + }) + } + _ => false, + } +} diff --git a/compiler/fmt/tests/test_fmt.rs b/compiler/fmt/tests/test_fmt.rs index 73a044c090..db0a632508 100644 --- a/compiler/fmt/tests/test_fmt.rs +++ b/compiler/fmt/tests/test_fmt.rs @@ -2249,7 +2249,7 @@ mod test_fmt { } #[test] - fn precedence_conflict_exponents() { + fn binop_parens() { expr_formats_same(indoc!( r#" if 4 == (6 ^ 6 ^ 7 ^ 8) then @@ -2258,6 +2258,39 @@ mod test_fmt { "Naturally" "# )); + + expr_formats_same(indoc!( + r#" + if 5 == 1 ^ 1 ^ 1 ^ 1 then + "Not buying it" + else + "True" + "# + )); + + expr_formats_to( + indoc!( + r#" + if (1 == 1) + && (2 == 1) && (3 == 2) then + "true" + else + "false" + "# + ), + indoc!( + r#" + if + (1 == 1) + && (2 == 1) + && (3 == 2) + then + "true" + else + "false" + "# + ), + ); } #[test]