Annotation ordering mishandles DocBlock boundary lines
Author: savinmikhailCreated Aug 12, 2026Updated Aug 12, 2026
Problem description
Annotation-ordering fixers mishandle multiline DocBlocks whose first and/or last annotations share a line with the opening or closing delimiter:
/** @return array<string, mixed>
* @throws RuntimeException */Annotation::getContent() includes the whole physical line, so an ordering fixer may move /** or */ together with an annotation.
Confirmed affected fixers:
phpdoc_ordercan generate invalid PHP containing*//**and exit with code 64.phpdoc_param_ordercan generate invalid PHP and exit with code 64.phpdoc_order_by_valuecan silently fail to order values because the delimiters become part of the comparison keys.
Removing annotations already handles boundary delimiters, but moving annotations does not.
Minimal reproducer CLI command
php-cs-fixer fix \
--dry-run \
--diff \
-vvv \
--using-cache=no \
--rules='{"phpdoc_order":true}' \
reproduce.phpMinimal reproducer code snippet
<?php
/** @return array<string, mixed>
* @throws RuntimeException */
function reproduce(): array
{
return [];
}Expected output (expanding both boundary lines before moving annotations):
<?php
/**
* @throws RuntimeException
* @return array<string, mixed>
*/
function reproduce(): array
{
return [];
}Already ordered compact DocBlocks should remain unchanged: ordering rules should only expand the boundaries when an actual move is required.
Actual phpdoc_order intermediate output
<?php
/**
* @throws RuntimeException *//** @return array<string, mixed>
function reproduce(): array
{
return [];
}The command exits with code 64 and reports an unterminated comment after fixing.
Environment
- PHP CS Fixer: 3.95.18
- PHP: 8.4.24
- Installation: Composer package
Source: PHP-CS-Fixer/PHP-CS-Fixer