Cycle between `braces_position` and `single_line_empty_body` on empty named bodies
Problem description
braces_position and single_line_empty_body form a no-op cycle on empty named-class bodies. braces_position expands ) {} to ) {\n }, then single_line_empty_body collapses it back. Both rules ship in @PhpCsFixer. Net diff contribution is zero, but both rules land in appliedFixers whenever another fixer rewrites the file.
Example has unrelated brace fix (class opening brace on the wrong line) alongside an empty named-method body with a multi-line signature. A full @PhpCsFixer run lists class_definition, braces_position, and single_line_empty_body in appliedFixers. Running class_definition alone produces a identical result but only lists class_definition in appliedFixers.
I think this is a bug rather than misconfiguration because both rules are part of @PhpCsFixer itself. No other ruleset is layered on top.
Past cyclical-rule conflicts in this project have been treated as bugs and fixed. See similar subsection
Possible fix
braces_position already has allow_single_line_empty_anonymous_classes and allow_single_line_anonymous_functions for the anonymous cases. A named-body equivalent, allow_single_line_empty_function_body, would resolve this. When enabled, braces_position would treat ) {} on named bodies as already valid and not report a fix.
Not sure I like this, because without that config, it's still incompatible.
Similar
- #1655 (
ParenthesisFixerandSpacesAfterSemicolonFixeronfor($i=0;$i<$c;), resolved by #1684) - #1822 (
no_empty_commentandsingle_blank_line_before_namespace): Introduced incompatibility feature
Confirmed non-duplicates
- #7298:
single_line_empty_bodycontradicts PSR-12. Closed not-planned. That report was specifically about layering@PSR12 + @PhpCsFixer. My case is@PhpCsFixeron its own. - #7962: proposed
only_for_constructorsconfig forsingle_line_empty_body. Closed unmerged. Adjacent issue, but approaches it from thesingle_line_empty_bodyside. - #9329: recent
braces_positionchange for anonymous functions in PSR rulesets. Different body kind.
Minimal reproducer CLI command
# A. Full @PhpCsFixer
php-cs-fixer fix Repro.php --rules=@PhpCsFixer --dry-run -vvv
# B. class_definition alone
php-cs-fixer fix Repro.php --rules=class_definition --dry-run -vvvMinimal reproducer code snippet
Repro.php as written (class brace on the same line as the class keyword):
<?php
class Repro {
public function __construct(
bool $a,
) {}
}Both runs below produce the same result:
<?php
class Repro
{
public function __construct(
bool $a,
) {}
}But running the full @PhpCsFixer on Repro.php reports all 3 as having run:
1) Repro.php (class_definition, braces_position, single_line_empty_body)Fixer version
3.94.2 7th Gear
PHP version
8.2.29
How do you run Fixer?
Composer package
Contribution Checks
- I have verified if this problem was already reported
- I am familiar with "Feature or bug?"
Source: PHP-CS-Fixer/PHP-CS-Fixer