From 28f9bb86f836753a4d9d490a2ae7ab8512106d67 Mon Sep 17 00:00:00 2001 From: Dextheking1 Date: Thu, 24 Sep 2026 02:00:14 +0200 Subject: [PATCH] fix: indent match arm body when conditions break onto multiple lines When a match arm's conditions don't fit on one line, the `=>` moves to its own indented line, but the body kept the arm's base indent for its own line breaks. This made nested structures (e.g. arrays, calls) indent relative to the wrong level. Wrap `=> ` and the body in `indentIfBreak` tied to the conditions group's break status, so the body gets the extra indent level only when the conditions actually broke. Fixes #2435 --- src/printer.mjs | 18 ++++++--- tests/match/__snapshots__/jsfmt.spec.mjs.snap | 40 ++++++++++++++++++- tests/match/match.php | 7 ++++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/printer.mjs b/src/printer.mjs index f789a340b..9a9286684 100644 --- a/src/printer.mjs +++ b/src/printer.mjs @@ -49,6 +49,7 @@ const { indent, dedent, ifBreak, + indentIfBreak, hardline, hardlineWithoutBreakParent, softline, @@ -2885,17 +2886,24 @@ function printNode(path, options, print) { ? hardline : ""; + const condsGroupId = Symbol("match-arm-conds"); + return [ "", hardline, maybeEmptyLineBetweenArms, ...maybeLeadingComment, group([ - group([conds, indent(line)]), - "=> ", - body, - maybeTrailingComma, - ...maybeTrailingComment, + group([conds, indent(line)], { id: condsGroupId }), + // When the conditions break onto multiple lines, the `=>` moves to + // its own indented line - the body then needs the same extra + // indent level for its own line breaks (see #2435). + indentIfBreak( + ["=> ", body, maybeTrailingComma, ...maybeTrailingComment], + { + groupId: condsGroupId, + } + ), ]), ].slice(!path.isFirst ? 0 : 1); }, "arms"); diff --git a/tests/match/__snapshots__/jsfmt.spec.mjs.snap b/tests/match/__snapshots__/jsfmt.spec.mjs.snap index 2279ebfaf..3852dd2a0 100644 --- a/tests/match/__snapshots__/jsfmt.spec.mjs.snap +++ b/tests/match/__snapshots__/jsfmt.spec.mjs.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`match.php 1`] = ` ====================================options===================================== @@ -70,6 +70,13 @@ match($really_really_really_really_really_really_really_really_long_variable_nam default => null }; +// https://github.com/prettier/plugin-php/issues/2435 +// When the conditions of a match arm break onto multiple lines, the body +// on the indented \`=>\` line must keep the extra indent for its own breaks. +echo match ($operation) { + "short", "really very long option 2" => SomeClass::fairlyLongMethodNameThatRunsOn($variable, ["short", "short"]), +}; + =====================================output===================================== null }; +// https://github.com/prettier/plugin-php/issues/2435 +// When the conditions of a match arm break onto multiple lines, the body +// on the indented \`=>\` line must keep the extra indent for its own breaks. +echo match ($operation) { + "short", + "really very long option 2" + => SomeClass::fairlyLongMethodNameThatRunsOn($variable, [ + "short", + "short" + ]) +}; + ================================================================================ `; @@ -231,6 +250,13 @@ match($really_really_really_really_really_really_really_really_long_variable_nam default => null }; +// https://github.com/prettier/plugin-php/issues/2435 +// When the conditions of a match arm break onto multiple lines, the body +// on the indented \`=>\` line must keep the extra indent for its own breaks. +echo match ($operation) { + "short", "really very long option 2" => SomeClass::fairlyLongMethodNameThatRunsOn($variable, ["short", "short"]), +}; + =====================================output===================================== null, }; +// https://github.com/prettier/plugin-php/issues/2435 +// When the conditions of a match arm break onto multiple lines, the body +// on the indented \`=>\` line must keep the extra indent for its own breaks. +echo match ($operation) { + "short", + "really very long option 2" + => SomeClass::fairlyLongMethodNameThatRunsOn($variable, [ + "short", + "short", + ]), +}; + ================================================================================ `; diff --git a/tests/match/match.php b/tests/match/match.php index 907a13086..fc668ecb3 100644 --- a/tests/match/match.php +++ b/tests/match/match.php @@ -59,3 +59,10 @@ match($really_really_really_really_really_really_really_really_long_variable_name) { default => null }; + +// https://github.com/prettier/plugin-php/issues/2435 +// When the conditions of a match arm break onto multiple lines, the body +// on the indented `=>` line must keep the extra indent for its own breaks. +echo match ($operation) { + "short", "really very long option 2" => SomeClass::fairlyLongMethodNameThatRunsOn($variable, ["short", "short"]), +};