fix: stable formatting for conditional expression as if/else body#797
Draft
bartlomieju wants to merge 1 commit into
Draft
fix: stable formatting for conditional expression as if/else body#797bartlomieju wants to merge 1 commit into
bartlomieju wants to merge 1 commit into
Conversation
A single-statement if/else body that is a conditional (ternary) expression
could format differently on each run: when the inline form exceeds the line
width, braces are added and the body moves to its own indented line, where the
ternary then fits on one line, but it was being wrapped based on the pre-brace
column. This left the formatter producing different output on the next run
("Formatting not stable").
Wrap the single non-block statement body in a new_line_group so its line-break
decisions are re-measured at the body's final indentation, matching how binary
and call expressions already behave (which were already stable).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a "Formatting not stable" non-idempotency: a single-statement
if/else ifbody that is a conditional (ternary) expression could format differently on each run.Reproduction
With the
denoconfig preset:Formatting once produces a wrapped ternary inside added braces; formatting again collapses it to one line:
} else if ("queue" === n) { - playing() - ? queue({ ids: [b] }) - : queue({ ids: [b] }); + playing() ? queue({ ids: [b] }) : queue({ ids: [b] }); }So the output is not a fixed point. In a consumer that re-formats to verify stability (e.g.
deno fmt, which retries up to 5 times), this surfaces asFormatting not stable. Bailed after 5 tries.Root cause
The inline form
} else if ("queue" === n) playing() ? ... : ...;is 82 columns, over the 80 limit, so:WhenNotSingleLineadds braces;The brace decision is re-evaluated via the printer's look-ahead/reevaluation, but
update_state_to_save_pointin dprint-core restores writer position without clearing already-resolved conditions, so the conditional expression's break decision (resolved at the inline column) sticks. Binary, call, and member-expression bodies don't hit this because they lay out inside a singlenew_line_groupthat re-fits cleanly on reprint; the conditional expression emits itsSpaceOrNewLinebreaks at the top level, outside such a group.Fix
Wrap the single non-block statement body in a
new_line_groupso its line-break decisions are re-measured at the body's final indentation, matching the behavior of the constructs that were already stable. The change is one line ingen_conditional_brace_body.Tests
tests/specs/deno/Deno_ConditionalExpressionStatementBody.txt. The spec runner formats twice (format_twice: true), so this asserts idempotency; it fails onmainand passes with the fix.Scope / caveats
This was found while investigating denoland/deno#26840 (large minified bundle bailing with "Formatting not stable"). This patch fixes the ternary-body class of instability. That particular file has additional, independent non-idempotency (e.g. single-statement bodies under multi-line-wrapped
ifheaders whose comma-sequence body sits at the width boundary), driven by the maintain-source-line-breaks behavior whenpreferSingleLineisfalse. Those are not addressed here; this PR is one self-contained increment.