diff --git a/crates/compiler/fmt/src/expr.rs b/crates/compiler/fmt/src/expr.rs index f6088b2309..b9f354cab9 100644 --- a/crates/compiler/fmt/src/expr.rs +++ b/crates/compiler/fmt/src/expr.rs @@ -1405,8 +1405,12 @@ fn fmt_binops<'a>( expr_lift_spaces(Parens::InOperator, buf.text.bump(), &loc_left_side.value); format_spaces(buf, lifted_left_side.before, Newlines::Yes, indent); + buf.indent(indent); + let line_indent = buf.cur_line_indent(); + let need_parens = matches!(lifted_left_side.item, Expr::BinOps(..)) - || starts_with_unary_minus(lifted_left_side.item); + || starts_with_unary_minus(lifted_left_side.item) + || (ends_with_closure(&lifted_left_side.item) && line_indent < indent); if need_parens { fmt_parens(&lifted_left_side.item, buf, indent); @@ -1451,6 +1455,17 @@ fn fmt_binops<'a>( format_spaces(buf, lifted_right_side.after, Newlines::Yes, indent); } +fn ends_with_closure(item: &Expr<'_>) -> bool { + match item { + Expr::Closure(..) => true, + Expr::Apply(expr, args, _) => args + .last() + .map(|a| ends_with_closure(&a.value)) + .unwrap_or_else(|| ends_with_closure(&expr.value)), + _ => false, + } +} + fn starts_with_unary_minus(item: Expr<'_>) -> bool { match item { Expr::UnaryOp( diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.formatted.roc new file mode 100644 index 0000000000..87104f1b38 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.formatted.roc @@ -0,0 +1,2 @@ +\j -> (e \B -> B) + > s \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.result-ast new file mode 100644 index 0000000000..43e6ff407f --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.result-ast @@ -0,0 +1,52 @@ +@0-16 SpaceAfter( + Closure( + [ + @1-2 Identifier { + ident: "j", + }, + ], + @4-16 BinOps( + [ + ( + @4-12 SpaceAfter( + Apply( + @4-5 Var { + module_name: "", + ident: "e", + }, + [ + @5-12 Closure( + [ + @6-7 SpaceAfter( + Tag( + "B", + ), + [ + Newline, + ], + ), + ], + @11-12 Tag( + "B", + ), + ), + ], + Space, + ), + [ + Newline, + ], + ), + @14-15 GreaterThan, + ), + ], + @15-16 Var { + module_name: "", + ident: "s", + }, + ), + ), + [ + Newline, + ], +) diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.roc new file mode 100644 index 0000000000..6def52fb43 --- /dev/null +++ b/crates/compiler/test_syntax/tests/snapshots/pass/double_closure_newlines_binop.expr.roc @@ -0,0 +1,3 @@ +\j->e\B + ->B + >s diff --git a/crates/compiler/test_syntax/tests/test_snapshots.rs b/crates/compiler/test_syntax/tests/test_snapshots.rs index 551bff7f8f..074da1119d 100644 --- a/crates/compiler/test_syntax/tests/test_snapshots.rs +++ b/crates/compiler/test_syntax/tests/test_snapshots.rs @@ -396,6 +396,7 @@ mod test_snapshots { pass/defs_suffixed_middle_extra_indents.moduledefs, pass/destructure_tag_assignment.expr, pass/docs.expr, + pass/double_closure_newlines_binop.expr, pass/double_parens_as_in_backpassing_pat.expr, pass/double_parens_comment_tuple_pat.expr, pass/double_space_before.expr,