Skip to content

Duplicated errors when that() is reused for multiple should() #303

Open
@Wirone

Description

@Wirone

Bug Report

Q A
BC Break no?
Library Version 0.2.32
PHP version 7.4.32

Summary

Consider such configuration:

return static function (Config $config): void {
    $srcClassSet = ClassSet::fromDir(__DIR__ . '/src');
    $rules = [];

    $rectors = Rule::allClasses()->that(new ResideInOneOfTheseNamespaces('Codito\Rector\Money\Rule'));
    $rules[] = $rectors->should(new HaveNameMatching('*Rector'))->because('this is Rector convention');
    $rules[] = $rectors
        ->should(new Extend(AbstractRector::class))
        ->because('we need satisfy Rector\'s contract for rules');

    $config->add($srcClassSet, ...$rules);
};

Since result of the should() is a BecauseParser it does not allow multiple expectations for the same selection, I wanted to reuse result of that() to make 2 separate rules. Unfortunately, it does not behave as I expected.

Current behavior

For class that does not satisfy both rules (empty Codito\Rector\Money\Rule\Foo class) I get:

Codito\Rector\Money\Rule\Foo has 4 violations
  should have a name that matches *Rector because this is Rector convention
  should extend Rector\Core\Rector\AbstractRector because this is Rector convention
  should have a name that matches *Rector because we need satisfy Rector's contract for rules
  should extend Rector\Core\Rector\AbstractRector because we need satisfy Rector's contract for rules

How to reproduce

Expected behavior

I would expect only 2 errors for such scenario:

Codito\Rector\Money\Rule\Foo has 2 violations
  should have a name that matches *Rector because this is Rector convention
  should extend Rector\Core\Rector\AbstractRector because we need satisfy Rector's contract for rules

Ideally, it would be great to be able to define rule like this:

return static function (Config $config): void {
    $srcClassSet = ClassSet::fromDir(__DIR__ . '/src');
    $rules = [];

    $rules[] = Rule::allClasses()
        ->that(new ResideInOneOfTheseNamespaces('Codito\Rector\Money\Rule'))
        ->should(new HaveNameMatching('*Rector'))
        ->andShould(new Extend(AbstractRector::class))
        ->because('we need to satisfy Rector\'s contract for rules and keep Rector naming convention');

    $config->add($srcClassSet, ...$rules);
};

and set multiple expectations for single rule.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions