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:

php
/** @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_order can generate invalid PHP containing *//** and exit with code 64.
  • phpdoc_param_order can generate invalid PHP and exit with code 64.
  • phpdoc_order_by_value can 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

bash
php-cs-fixer fix \
  --dry-run \
  --diff \
  -vvv \
  --using-cache=no \
  --rules='{"phpdoc_order":true}' \
  reproduce.php

Minimal reproducer code snippet

php
<?php

/** @return array<string, mixed>
 * @throws RuntimeException */
function reproduce(): array
{
    return [];
}

Expected output (expanding both boundary lines before moving annotations):

php
<?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
<?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