refactor(formatter): improve and simplify the handling of AssignmentLikeLayout::BreakAfterOperator#16869
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
CodSpeed Performance ReportMerging #16869 will not alter performanceComparing Summary
Footnotes
|
fd3a045 to
5ff1074
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors the AssignmentLikeLayout::BreakAfterOperator handling in the formatter to align with Prettier's latest shouldBreakAfterOperator logic. The changes simplify the code by removing outdated logic originally ported from Biome and consolidating expression unwrapping logic into a more comprehensive helper function.
Key Changes
- Simplified layout determination logic by moving string literal and poorly breakable chain checks into
should_break_after_operator - Enhanced
get_innermost_expressionhelper (formerlyget_last_non_unary_argument) to handle more expression types includingAwaitExpression,YieldExpression, andTSNonNullExpression - Added
is_left_shortparameter toshould_break_after_operatorto support Prettier-aligned decision-making
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
The refactor improves readability and aligns the high-level structure with Prettier, but get_innermost_expression(...) broadens unwrapping to include await/yield, which can change BreakAfterOperator decisions in non-trivial ways and may not be “exact Prettier alignment” without tests. The is_left_short rule is now split across get_layout and should_break_after_operator, increasing coupling and drift risk. Tightening the helper’s scope and adding targeted regression tests would make the behavior change safer and easier to audit.
Additional notes (1)
- Maintainability |
crates/oxc_formatter/src/utils/assignment_like.rs:404-404
The earlieris_left_shortearly-return (NeverBreakAfterOperator) was removed and replaced with_ if is_left_short => falseinsideshould_break_after_operator, plus anif !left_may_break && (is_left_short || matches!(...))condition.
This changes control flow subtly: is_left_short now prevents BreakAfterOperator even in cases that previously might have been decided earlier in get_layout (depending on surrounding conditions like left_may_break). This may be intended to match Prettier, but it also means the “short left” rule is now distributed across two places, increasing the chance of divergence later.
If is_left_short is truly part of the should_break_after_operator heuristic (as in Prettier), consider fully centralizing it there and avoiding extra coupling in get_layout’s later NeverBreakAfterOperator clause.
Summary of changes
What changed
- Removed the now-unused
std::iterimport. - Updated
AssignmentLikeLayoutdecision logic to passis_left_shortintoshould_break_after_operator(...)and to consolidate theNeverBreakAfterOperatorearly-return conditions. - Refactored
should_break_after_operatorto more closely follow Prettier’sshouldBreakAfterOperatorbehavior by:- short-circuiting when
is_left_shortistrue(after handling a few explicit cases) - simplifying the fallback checks to use a new helper
get_innermost_expression(...).
- short-circuiting when
- Replaced
get_last_non_unary_argument(...)withget_innermost_expression(...), expanding the “unwrap” behavior to includeTSNonNullExpression,AwaitExpression, andYieldExpression.
Links:
- Prettier reference noted in-code:
assignment.js#L235-L263.
…LikeLayout::BreakAfterOperator` (#16869) Align handling of `AssignmentLikeLayout::BreakAfterOperator` with newst [Prettier's shouldBreakAfterOperator](https://github.com/prettier/prettier/blob/0273e33fc691e28e4ab3f3c8ee86918b65cf823d/src/language-js/print/assignment.js#L195-L264) logic The initial implementation is ported from Biome; however, some logic is outdated and diverges from Prettier, so we align exactly with Prettier to avoid unexpected edge cases.
5ff1074 to
95ef465
Compare
Merge activity
|
95ef465 to
5ff1074
Compare
…LikeLayout::BreakAfterOperator` (#16869) Align handling of `AssignmentLikeLayout::BreakAfterOperator` with newst [Prettier's shouldBreakAfterOperator](https://github.com/prettier/prettier/blob/0273e33fc691e28e4ab3f3c8ee86918b65cf823d/src/language-js/print/assignment.js#L195-L264) logic The initial implementation is ported from Biome; however, some logic is outdated and diverges from Prettier, so we align exactly with Prettier to avoid unexpected edge cases.
5ff1074 to
58bced1
Compare

Align handling of
AssignmentLikeLayout::BreakAfterOperatorwith newst Prettier's shouldBreakAfterOperator logicThe initial implementation is ported from Biome; however, some logic is outdated and diverges from Prettier, so we align exactly with Prettier to avoid unexpected edge cases.