Skip to content

Fix formatting oscillation in if-then-else branches#2800

Open
MisterDA wants to merge 1 commit into
ocaml-ppx:mainfrom
MisterDA:fix-2799
Open

Fix formatting oscillation in if-then-else branches#2800
MisterDA wants to merge 1 commit into
ocaml-ppx:mainfrom
MisterDA:fix-2799

Conversation

@MisterDA
Copy link
Copy Markdown
Contributor

@MisterDA MisterDA commented Apr 24, 2026

When a comment sits between a keyword (then/else) and certain branch
expressions (begin...end wrapping match/try/function/ifthenelse, or bare
match/try/function/ifthenelse), the comment would alternate between
"after keyword" and "before expression" placements across formatting
iterations. This caused branch_pro to compute different indentation each
time, producing "formatting did not stabilize after 10 iterations".

The fix detects these oscillation-prone patterns and ensures stable
formatting regardless of the initial comment placement:

  • In Fmt_ast, when a branch matches needs_raw_cmts_after_kw, extract
    "after keyword" comments without breaks and override branch_pro using
    Params.raw_cmts_branch_pro (which computes mode-appropriate
    break+indent+comment output).

  • In Params, branch_pro_with_cmts detects comments "before expression"
    (the alternate placement) and forces a break, producing the same layout
    as the "after keyword" path.

  • For begin...end branches, branch_pro checks for comments before the
    inner expression (not just the begin...end node) to handle the case
    where the comment migrates inside the begin...end scope.

Affected modes: Fit_or_vertical, Compact (profile=conventional).

Closes #2799.

Comment thread lib/Fmt_ast.ml Outdated
Comment thread lib/Cmts.ml Outdated
Comment thread lib/Params.ml Outdated
@MisterDA
Copy link
Copy Markdown
Contributor Author

MisterDA commented Apr 30, 2026

Thanks for the review, here's a revised version of the patch with your comments.
Not sure where the build failures on Windows come from, and I think they're unrelated.

Comment thread lib/Fmt_ast.ml Outdated
Comment thread lib/Params.ml Outdated
~parens_bch ~parens_prev_bch ~xcond ~xbch ~expr_loc ~fmt_infix_ext_attrs
~infix_ext_attrs ~fmt_cond ~cmts_before_kw ~cmts_after_kw =
~infix_ext_attrs ~fmt_cond ~cmts_before_kw ~cmts_after_kw
~cmts_after_kw_raw =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like this cmts_after_kw_raw argument. I tried to get rid of it by passing Cmts.fmt_after ~pro:noop ~epi:noop .. to ~cmts_after_kw but it's very hard due to the many different states this creates.

I won't merge a new argument to get_if_then_else.

Copy link
Copy Markdown
Contributor Author

@MisterDA MisterDA May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude found another workaround. Let me know if it's satisfying or not.
EDIT: not sure how to reproduce the CI failures.

When a comment sits between a keyword (then/else) and certain branch
expressions (begin...end wrapping match/try/function/ifthenelse, or bare
match/try/function/ifthenelse), the comment would alternate between
"after keyword" and "before expression" placements across formatting
iterations. This caused branch_pro to compute different indentation each
time, producing "formatting did not stabilize after 10 iterations".

The fix detects these oscillation-prone patterns and ensures stable
formatting regardless of the initial comment placement:

- In Fmt_ast, when a branch matches `needs_raw_cmts_after_kw`, extract
  "after keyword" comments without breaks and override branch_pro using
  `Params.raw_cmts_branch_pro` (which computes mode-appropriate
  break+indent+comment output).

- In Params, `branch_pro_with_cmts` detects comments "before expression"
  (the alternate placement) and forces a break, producing the same layout
  as the "after keyword" path.

- For begin...end branches, `branch_pro` checks for comments before the
  inner expression (not just the begin...end node) to handle the case
  where the comment migrates inside the begin...end scope.

Affected modes: Fit_or_vertical, Compact (profile=conventional).

Assisted-by: GitHub Copilot:claude-opus-4-20250514
@MisterDA MisterDA changed the title Fix formatting oscillation with if-then-else=fit-or-vertical and begin…end Fix formatting oscillation in if-then-else branches May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Unstable comment exceeding the margin with if-then-else=fit-or-vertical

2 participants