Php-cs-fixer: How to ignore specific lines?

Created on 29 Jun 2018  Â·  3Comments  Â·  Source: FriendsOfPHP/PHP-CS-Fixer

This is a really great project, I use it every day with pretty much the most strict config possible :smile:. The problem I've come across is that sometimes there's a legitimate reason to break one of the rules, but I can't seem to find a way to get cs-fixer to ignore the line that the break occurs on.

For example, I have php_unit_strict turned on, because 99% of the time, I want strict comparisons in phpunit. However every now and then I need to compare 2 objects that are not the same, but should be equal:

$expectedObject = (new Foo)->setValue('foo');
$actualObject = $classUnderTest->getFoo();

static::assertEquals($expectedObject, $actualObject);

The Foo object here has many properties on it, so I don't want to go through and assert them all. assertEquals works great here, but only here. Everywhere else I want assertSame being used.

Essentially what I'm looking for is some way to ignore that specific line. PhpCS achieves it with // phpcs:ignore comments and psalm uses /** @psalm-suppress */ docblock annotations. Is there anything like this in cs-fixer?

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

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

=> 7.2.6

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

=> 2.12.1

The command you use to run PHP CS Fixer:

$ php vendor/bin/php-cs-fixer fix src tests --verbose --format junit --config .php_cs

The configuration file you are using, if any:

<?php

return PhpCsFixer\Config::create()
    ->setRules([
        '@Symfony'                               => true,
        '@PHP71Migration'                        => true,
        '@PHP71Migration:risky'                  => true,
        '@DoctrineAnnotation'                    => true,
        '@PHPUnit60Migration:risky'              => true,
        'array_syntax'                           => ['syntax' => 'short'],
        'binary_operator_spaces'                 => ['default' => 'align_single_space_minimal'],
        'align_multiline_comment'                => ['comment_type' => 'phpdocs_like'],
        'combine_consecutive_issets'             => true,
        'combine_consecutive_unsets'             => true,
        'compact_nullable_typehint'              => true,
        'escape_implicit_backslashes'            => true,
        'explicit_indirect_variable'             => true,
        'explicit_string_variable'               => true,
        'final_internal_class'                   => true,
        'linebreak_after_opening_tag'            => true,
        'list_syntax'                            => ['syntax' => 'short'],
        'mb_str_functions'                       => true,
        'method_argument_space'                  => ['ensure_fully_multiline' => true],
        'method_chaining_indentation'            => true,
        'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
        'native_function_invocation'             => true,
        'no_php4_constructor'                    => true,
        'no_short_echo_tag'                      => true,
        'no_superfluous_elseif'                  => true,
        'no_useless_else'                        => true,
        'no_useless_return'                      => true,
        'ordered_class_elements'                 => true,
        'ordered_imports'                        => true,
        'php_unit_strict'                        => true,
        'phpdoc_order'                           => true,
        'phpdoc_types_order'                     => true,
        'simplified_null_return'                 => true,
        'strict_comparison'                      => true,
        'strict_param'                           => true,
    ])
    ->setRiskyAllowed(true)
;

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

  • before running PHP CS Fixer (no changes):
$expectedObject = (new Foo)->setValue('foo');
$actualObject = $classUnderTest->getFoo();

static::assertEquals($expectedObject, $actualObject);
  • with unexpected changes applied when running PHP CS Fixer:
$expectedObject = (new Foo)->setValue('foo');
$actualObject = $classUnderTest->getFoo();

static::assertSame($expectedObject, $actualObject);
  • with the changes you expected instead:
$expectedObject = (new Foo)->setValue('foo');
$actualObject = $classUnderTest->getFoo();

static::assertEquals($expectedObject, $actualObject);
kinquestion

Most helpful comment

This is a design decision that you shall not allow for exceptions per block of code.
It may or may not be introduced in the future, depends on amount of ppl requesting it and one who would take a challenge to implement it.

Currently, if you are really in need, you can disable file from being fixed at all. But that would mean it would not be fixed by any other rules as well.

Instead, I would strongly suggest to not violate the rule and compare your objects properly by creating a comparator for them.
Imagine, that currently the objects could represent the very same class type and share concrete implementation. But with time, it may happen that they will no longer share it, but they would share common interface instead, and have different concrete implementations (eg, one is pure DTO, one retrieve values with lazy-loading approach, one is caching, ....) - then, assertEquals will fail. With proper Comparator, especially if it would be accepting an interfaces and not concrete solution - that issue will never happen.
Also, remember that assertEquals is not well defined assertion which behavior is not the same for all PHPUnit versions, eg recently, assertEquals('0.0', '0.00') would fail.

For bigger discussion I would suggest to visit our support channel on gitter.

All 3 comments

This is a design decision that you shall not allow for exceptions per block of code.
It may or may not be introduced in the future, depends on amount of ppl requesting it and one who would take a challenge to implement it.

Currently, if you are really in need, you can disable file from being fixed at all. But that would mean it would not be fixed by any other rules as well.

Instead, I would strongly suggest to not violate the rule and compare your objects properly by creating a comparator for them.
Imagine, that currently the objects could represent the very same class type and share concrete implementation. But with time, it may happen that they will no longer share it, but they would share common interface instead, and have different concrete implementations (eg, one is pure DTO, one retrieve values with lazy-loading approach, one is caching, ....) - then, assertEquals will fail. With proper Comparator, especially if it would be accepting an interfaces and not concrete solution - that issue will never happen.
Also, remember that assertEquals is not well defined assertion which behavior is not the same for all PHPUnit versions, eg recently, assertEquals('0.0', '0.00') would fail.

For bigger discussion I would suggest to visit our support channel on gitter.

closing in favor of https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/3317 , not because this is not a nice report, but so the discussion is not across multiple issues.
Please resume the talks there : )

Was this page helpful?
0 / 5 - 0 ratings