Php-cs-fixer: only psalm annotations not recognised as docblock and a * is striped

Created on 12 Jun 2019  路  8Comments  路  Source: FriendsOfPHP/PHP-CS-Fixer

Hi,

Whenever I have a docblock annotation with only a @psalm-* annotation in it, cs fixer does not recognize it as a docblock and therefore strips the last * of the opening /**.

Might be just a configuration option, or a bug...

When reporting an issue (bug) please provide the following information:

The PHP version you are using ($ php -v):

PHP 7.2.19 (cli) (built: Jun 1 2019 00:03:09) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Xdebug v2.7.2, Copyright (c) 2002-2019, by Derick Rethans
with Zend OPcache v7.2.19, Copyright (c) 1999-2018, by Zend Technologies

PHP CS Fixer version you are using ($ php-cs-fixer -V):

PHP CS Fixer 2.15.1 Europe Round by Fabien Potencier and Dariusz Ruminski

The command you use to run PHP CS Fixer:

php-cs-fixer fix -v --diff

The configuration file you are using, if any:

private $defaults = [
        '@PHP71Migration' => true,
        '@PSR2' => true,
        '@Symfony' => true,
        'array_syntax' => ['syntax' => 'short'],
        'binary_operator_spaces' => [
            'align_double_arrow' => false,
            'align_equals' => false,
        ],
        'blank_line_after_namespace' => true,
        'blank_line_after_opening_tag' => true,
        'blank_line_before_return' => true,
        'braces' => true,
        'cast_spaces' => true,
        'class_definition' => true,
        'combine_consecutive_unsets' => true,
        'concat_space' => false,
        'declare_strict_types' => true,
        'elseif' => true,
        'encoding' => true,
        'full_opening_tag' => true,
        'function_declaration' => true,
        'function_typehint_space' => true,
        'hash_to_slash_comment' => true,
        'header_comment' => [
            'commentType' => 'PHPDoc',
            'header' => 'PLHW was here at `%package%` in `%year%`! Please create a .docheader in the project root and run `composer cs-fix`',
            'location' => 'after_open',
            'separate' => 'both',
        ],
        'include' => true,
        'indentation_type' => true,
        'line_ending' => true,
        'linebreak_after_opening_tag' => true,
        'lowercase_constants' => true,
        'lowercase_keywords' => true,
        'method_argument_space' => true,
        'method_separation' => true,
        'modernize_types_casting' => true,
        'native_function_casing' => true,
        'native_function_invocation' => ['exclude' => ['time']],
        'new_with_braces' => true,
        'no_alias_functions' => true,
        'no_blank_lines_after_class_opening' => true,
        'no_closing_tag' => true,
        'no_empty_statement' => true,
        'no_extra_consecutive_blank_lines' => true,
        'no_leading_import_slash' => true,
        'no_leading_namespace_whitespace' => true,
        'no_multiline_whitespace_around_double_arrow' => true,
        'no_multiline_whitespace_before_semicolons' => true,
        'no_short_bool_cast' => true,
        'no_short_echo_tag' => true,
        'no_singleline_whitespace_before_semicolons' => true,
        'no_spaces_around_offset' => true,
        'no_spaces_inside_parenthesis' => true,
        'no_trailing_comma_in_list_call' => true,
        'no_trailing_comma_in_singleline_array' => true,
        'no_trailing_whitespace_in_comment' => true,
        'no_unneeded_control_parentheses' => true,
        'no_unreachable_default_argument_value' => true,
        'no_unused_imports' => true,
        'no_useless_else' => true,
        'no_useless_return' => true,
        'no_whitespace_before_comma_in_array' => true,
        'no_whitespace_in_blank_line' => true,
        'normalize_index_brace' => true,
        'not_operator_with_successor_space' => true,
        'object_operator_without_whitespace' => true,
        'ordered_imports' => true,
        'phpdoc_indent' => true,
        'phpdoc_inline_tag' => true,
        'psr4' => true,
        'return_type_declaration' => true,
        'semicolon_after_instruction' => true,
        'short_scalar_cast' => true,
        'simplified_null_return' => false,
        'single_blank_line_at_eof' => true,
        'single_class_element_per_statement' => true,
        'single_import_per_statement' => true,
        'single_line_after_imports' => true,
        'single_quote' => true,
        'standardize_not_equals' => true,
        'strict_comparison' => true,
        'switch_case_semicolon_to_colon' => true,
        'switch_case_space' => true,
        'ternary_operator_spaces' => true,
        'trailing_comma_in_multiline_array' => true,
        'trim_array_spaces' => true,
        'unary_operator_spaces' => true,
        'visibility_required' => true,
        'whitespace_after_comma_in_array' => true,
        'void_return' => true,
    ];

If applicable, please provide minimum samples of PHP code (as plain text, not screenshots):

  • before running PHP CS Fixer (no changes):
    /** @psalm-suppress TooManyArguments */
  • with unexpected changes applied when running PHP CS Fixer:
    /* @psalm-suppress TooManyArguments */
  • with the changes you expected instead:
    /** @psalm-suppress TooManyArguments */
kinfeature request

Most helpful comment

Hi,

This is indeed done by the fixer because the PHPDoc is not used for a structural element.
I think it would be nice to allow the rule be configurable by stating which PHPDoc's not to touch, maybe by defining regex expressions?

All 8 comments

What code do you have after PHPDoc? You are using phpdoc_to_comment (as part of @Symfony) and it converts when the comment is not before structural element.

$runQuery = function (Prooph\EventStore\Projection\Query $query, DateTimeInterface $time): array {
    $query->reset();

    /** @psalm-suppress TooManyArguments */
    $query
        ->init(/**
         * @return int[]
         *
         * @psalm-return array{approved:int, incepted:int, cloned:int, placed:int, rejected:int}
         */
            function (): array {
                return [
                    'approved' => 0,
                    'incepted' => 0,
                    'cloned' => 0,
                    'placed' => 0,
                    'rejected' => 0,
                ];
            })
        ->fromStream('dossier_order', (new MetadataMatcher())->withMetadataMatch(
            'created_at',
            Operator::GREATER_THAN_EQUALS(),
            $time->format('Y-m-d\TH:i:s.u'),
            FieldType::MESSAGE_PROPERTY())
        )
        ->when([
            EventName::order_hasBeenIncepted => function (array $state, Event\Order\HasBeenIncepted $event): array {
                ++$state['incepted'];

                return $state;
            },
            EventName::order_hasBeenCloned => function (array $state, Event\Order\HasBeenCloned $event): array {
                ++$state['cloned'];

                return $state;
            },
            EventName::order_hasBeenPlaced => function (array $state, Event\Order\HasBeenPlaced $event): array {
                ++$state['placed'];

                return $state;
            },
            EventName::order_hasBeenRejected => function (array $state, Event\Order\HasBeenRejected $event): array {
                ++$state['rejected'];

                return $state;
            },
            EventName::order_hasBeenApproved => function (array $state, Event\Order\HasBeenApproved $event): array {
                ++$state['approved'];

                return $state;
            },
        ])
        ->run();

    return $query->getState();
};
ERROR: TooManyArguments - bin/test-projection.php:67:11 - Too many arguments for method Prooph\EventStore\Projection\Query::fromstream - expecting 1 but saw 2
        ->fromStream('dossier_order', (new MetadataMatcher())->withMetadataMatch(

fromStream has an incorrect interface, but this code is valid, therefore attempting to suppress the error

I have the same problem (using @Symfony ruleset), the docblock is after an assignment:

/** @var psalm-suppress ... */
$this->foo = 'bar';

Hi,

This is indeed done by the fixer because the PHPDoc is not used for a structural element.
I think it would be nice to allow the rule be configurable by stating which PHPDoc's not to touch, maybe by defining regex expressions?

Same problem, * gets removed for trait usage like:

class ContractRepository extends ServiceEntityRepository
{
    /** @use RepositoryUtilsTrait<Contract> */
    use RepositoryUtilsTrait;

which breaks psalm.

This will allow you to solve your problems.

I'm having this issue too, with PHPStan in my case. I have multiple /** @var ... around in my code to fix types and this breaks them. I opted to 'phpdoc_to_comment' => false as an hotfix.

What code do you have after PHPDoc? You are using phpdoc_to_comment (as part of @Symfony) and it converts when the comment is not before structural element.

Can someone solve this? Defining this based on "before structural element" is not that much helpful as this does not work (annotation is fixed to // @var Connection $connection):

/** @var Connection $connection */
return $connection->something();

but this (with assign to a totally unrelated variable) works (ie. kept without changes):

/** @var Connection $connection */
$x = 'unrelated';
Was this page helpful?
0 / 5 - 0 ratings