Skip to content

Commit d785a78

Browse files
committed
Bond version-specific rules to composer package constraints
Add ComposerPackageConstraintInterface to rules that emit APIs which only exist since a specific PHPUnit version, with the version verified against the phpunit/phpunit git history: * AllowMockObjectsWhereParentClassRector, AllowMockObjectsForDataProviderRector and AllowMockObjectsWithoutExpectationsAttributeRector >=12.5.2, as the #[AllowMockObjectsWithoutExpectations] attribute was added there * RemoveOverrideFinalConstructTestCaseRector >=12.0.3, as TestCase::__construct() was declared final there * InlineStubPropertyToCreateStubMethodCallRector, SingleMockPropertyTypeRector and ChangeMockObjectReturnUnionToIntersectionRector >=11.0, to match their already bonded stub/mock siblings * AddProphecyTraitRector to phpspec/prophecy-phpunit, that provides the trait Bond the configured renames the same way: * getInvocationCount() => numberOfInvocations() to PHPUnit >=10.0 * assertObjectHasAttribute() => assertObjectHasProperty() to PHPUnit >=10.1 * expectExceptionMessage() => expectExceptionMessageIsOrContains() to PHPUnit >=13.2 The newly bonded rules move to the composer-based set, so they apply to any project with a matching PHPUnit version, not only to a single upgrade set.
1 parent afebdca commit d785a78

15 files changed

Lines changed: 148 additions & 36 deletions

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"php": ">=8.4"
88
},
99
"require-dev": {
10+
"phpspec/prophecy-phpunit": "^2.5",
1011
"phpstan/extension-installer": "^1.4",
1112
"phpstan/phpstan": "^2.2",
1213
"phpstan/phpstan-deprecation-rules": "^2.0",

config/sets/composer-based.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
use Rector\PHPUnit\PHPUnit110\Rector\ClassMethod\MockObjectArgCreateStubToCreateMockRector;
2121
use Rector\PHPUnit\PHPUnit120\Rector\CallLike\CreateStubInCoalesceArgRector;
2222
use Rector\PHPUnit\PHPUnit120\Rector\CallLike\CreateStubOverCreateMockArgRector;
23+
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsForDataProviderRector;
24+
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsWhereParentClassRector;
25+
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsWithoutExpectationsAttributeRector;
2326
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AssertIsTypeMethodCallRector;
2427
use Rector\PHPUnit\PHPUnit120\Rector\Class_\PropertyCreateMockToCreateStubRector;
28+
use Rector\PHPUnit\PHPUnit120\Rector\Class_\RemoveOverrideFinalConstructTestCaseRector;
2529
use Rector\PHPUnit\PHPUnit120\Rector\ClassMethod\ExpressionCreateMockToCreateStubRector;
2630
use Rector\PHPUnit\PHPUnit120\Rector\Property\MockObjectVarToStubRector;
2731
use Rector\PHPUnit\ValueObject\AnnotationWithValueToAttribute;
@@ -61,6 +65,14 @@
6165
// deprecated in PHPUnit 11.5
6266
AssertContainsOnlyMethodCallRector::class,
6367
AssertIsTypeMethodCallRector::class,
68+
69+
// the TestCase::__construct() is final since PHPUnit 12.0.3
70+
RemoveOverrideFinalConstructTestCaseRector::class,
71+
72+
// the AllowMockObjectsWithoutExpectations attribute exists since PHPUnit 12.5.2
73+
AllowMockObjectsWhereParentClassRector::class,
74+
AllowMockObjectsForDataProviderRector::class,
75+
AllowMockObjectsWithoutExpectationsAttributeRector::class,
6476
]);
6577

6678
// both attributes were added in PHPUnit 10.0

config/sets/phpunit100.php

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,6 @@
3131
// https://github.com/sebastianbergmann/phpunit/issues/4087
3232
new MethodCallRename('PHPUnit\Framework\Assert', 'assertRegExp', 'assertMatchesRegularExpression'),
3333

34-
// https://github.com/sebastianbergmann/phpunit/issues/5220
35-
new MethodCallRename('PHPUnit\Framework\Assert', 'assertObjectHasAttribute', 'assertObjectHasProperty'),
36-
new MethodCallRename('PHPUnit\Framework\Assert', 'assertObjectNotHasAttribute', 'assertObjectNotHasProperty'),
37-
38-
new MethodCallRename(
39-
'PHPUnit\Framework\MockObject\Rule\InvocationOrder',
40-
'getInvocationCount',
41-
'numberOfInvocations'
42-
),
43-
4434
// https://github.com/sebastianbergmann/phpunit/issues/4090
4535
new MethodCallRename('PHPUnit\Framework\Assert', 'assertNotRegExp', 'assertDoesNotMatchRegularExpression'),
4636

@@ -102,4 +92,21 @@
10292
'expectExceptionMessageMatches'
10393
),
10494
]);
95+
96+
// the numberOfInvocations() method was added in PHPUnit 10.0
97+
// @see https://github.com/sebastianbergmann/phpunit/commit/2ba8b7fded44a1a75cf5712a3b7310a8de0b6bb8
98+
$rectorConfig->ruleWithConfigurationComposerVersionBound(RenameMethodRector::class, [
99+
new MethodCallRename(
100+
'PHPUnit\Framework\MockObject\Rule\InvocationOrder',
101+
'getInvocationCount',
102+
'numberOfInvocations'
103+
),
104+
], 'phpunit/phpunit', '>=10.0');
105+
106+
// the assertObjectHasProperty() and assertObjectNotHasProperty() methods were added in PHPUnit 10.1
107+
// @see https://github.com/sebastianbergmann/phpunit/issues/5220
108+
$rectorConfig->ruleWithConfigurationComposerVersionBound(RenameMethodRector::class, [
109+
new MethodCallRename('PHPUnit\Framework\Assert', 'assertObjectHasAttribute', 'assertObjectHasProperty'),
110+
new MethodCallRename('PHPUnit\Framework\Assert', 'assertObjectNotHasAttribute', 'assertObjectNotHasProperty'),
111+
], 'phpunit/phpunit', '>=10.1');
105112
};

config/sets/phpunit120.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
declare(strict_types=1);
44

55
use Rector\Config\RectorConfig;
6-
use Rector\PHPUnit\PHPUnit120\Rector\Class_\RemoveOverrideFinalConstructTestCaseRector;
76
use Rector\PHPUnit\Set\PHPUnitSetList;
87

98
return static function (RectorConfig $rectorConfig): void {
9+
// RemoveOverrideFinalConstructTestCaseRector is registered there, guarded by composer package constraint,
10+
// as the TestCase::__construct() is final since PHPUnit 12.0.3 only
1011
$rectorConfig->sets([PHPUnitSetList::PHPUNIT_MOCK_TO_STUB, PHPUnitSetList::COMPOSER_BASED]);
11-
12-
$rectorConfig->rules([RemoveOverrideFinalConstructTestCaseRector::class]);
1312
};

config/sets/phpunit125.php

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,11 @@
33
declare(strict_types=1);
44

55
use Rector\Config\RectorConfig;
6-
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsForDataProviderRector;
7-
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsWhereParentClassRector;
8-
use Rector\PHPUnit\PHPUnit120\Rector\Class_\AllowMockObjectsWithoutExpectationsAttributeRector;
6+
use Rector\PHPUnit\Set\PHPUnitSetList;
97

108
return static function (RectorConfig $rectorConfig): void {
11-
$rectorConfig->rules([
12-
AllowMockObjectsWhereParentClassRector::class,
13-
AllowMockObjectsForDataProviderRector::class,
14-
15-
// experimental, from PHPUnit 12.5.2
16-
// @see https://github.com/sebastianbergmann/phpunit/commit/24c208d6a340c3071f28a9b5cce02b9377adfd43
17-
AllowMockObjectsWithoutExpectationsAttributeRector::class,
18-
]);
9+
// the AllowMockObjects* rules are registered there, guarded by composer package constraint,
10+
// as the #[AllowMockObjectsWithoutExpectations] attribute exists since PHPUnit 12.5.2
11+
// @see https://github.com/sebastianbergmann/phpunit/commit/24c208d6a340c3071f28a9b5cce02b9377adfd43
12+
$rectorConfig->sets([PHPUnitSetList::COMPOSER_BASED]);
1913
};

config/sets/phpunit130.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212
// guarded by composer package constraint
1313
$rectorConfig->sets([PHPUnitSetList::COMPOSER_BASED]);
1414

15-
$rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [
16-
// @see https://github.com/sebastianbergmann/phpunit/issues/6560
17-
new MethodCallRename('PHPUnit\Framework\TestCase', 'expectExceptionMessage', 'expectExceptionMessageIsOrContains'),
18-
]);
15+
// the expectExceptionMessageIsOrContains() method was added in PHPUnit 13.2
16+
// @see https://github.com/sebastianbergmann/phpunit/issues/6560
17+
$rectorConfig->ruleWithConfigurationComposerVersionBound(RenameMethodRector::class, [
18+
new MethodCallRename(
19+
'PHPUnit\Framework\TestCase',
20+
'expectExceptionMessage',
21+
'expectExceptionMessageIsOrContains'
22+
),
23+
], 'phpunit/phpunit', '>=13.2');
1924
};

rules/CodeQuality/Rector/ClassMethod/ChangeMockObjectReturnUnionToIntersectionRector.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
use Rector\PHPUnit\Enum\PHPUnitClassName;
1818
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
1919
use Rector\Rector\AbstractRector;
20+
use Rector\VersionBonding\Contract\ComposerPackageConstraintInterface;
21+
use Rector\VersionBonding\ValueObject\ComposerPackageConstraint;
2022
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
2123
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
2224

2325
/**
2426
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\ClassMethod\ChangeMockObjectReturnUnionToIntersectionRector\ChangeMockObjectReturnUnionToIntersectionRectorTest
2527
*/
26-
final class ChangeMockObjectReturnUnionToIntersectionRector extends AbstractRector
28+
final class ChangeMockObjectReturnUnionToIntersectionRector extends AbstractRector implements ComposerPackageConstraintInterface
2729
{
2830
public function __construct(
2931
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
@@ -32,6 +34,11 @@ public function __construct(
3234
) {
3335
}
3436

37+
public function provideComposerPackageConstraint(): ComposerPackageConstraint
38+
{
39+
return new ComposerPackageConstraint('phpunit/phpunit', '>=11.0');
40+
}
41+
3542
public function getNodeTypes(): array
3643
{
3744
return [ClassMethod::class];

rules/CodeQuality/Rector/Class_/InlineStubPropertyToCreateStubMethodCallRector.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
2828
use Rector\Rector\AbstractRector;
2929
use Rector\ValueObject\MethodName;
30+
use Rector\VersionBonding\Contract\ComposerPackageConstraintInterface;
31+
use Rector\VersionBonding\ValueObject\ComposerPackageConstraint;
3032
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
3133
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
3234

3335
/**
3436
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\InlineStubPropertyToCreateStubMethodCallRector\InlineStubPropertyToCreateStubMethodCallRectorTest
3537
*/
36-
final class InlineStubPropertyToCreateStubMethodCallRector extends AbstractRector
38+
final class InlineStubPropertyToCreateStubMethodCallRector extends AbstractRector implements ComposerPackageConstraintInterface
3739
{
3840
public function __construct(
3941
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
@@ -44,6 +46,11 @@ public function __construct(
4446
) {
4547
}
4648

49+
public function provideComposerPackageConstraint(): ComposerPackageConstraint
50+
{
51+
return new ComposerPackageConstraint('phpunit/phpunit', '>=11.0');
52+
}
53+
4754
public function getRuleDefinition(): RuleDefinition
4855
{
4956
return new RuleDefinition(

rules/CodeQuality/Rector/Class_/SingleMockPropertyTypeRector.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,26 @@
1111
use PHPUnit\Framework\MockObject\MockObject;
1212
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
1313
use Rector\Rector\AbstractRector;
14+
use Rector\VersionBonding\Contract\ComposerPackageConstraintInterface;
15+
use Rector\VersionBonding\ValueObject\ComposerPackageConstraint;
1416
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1517
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
1618

1719
/**
1820
* @see \Rector\PHPUnit\Tests\CodeQuality\Rector\Class_\SingleMockPropertyTypeRector\SingleMockPropertyTypeRectorTest
1921
*/
20-
final class SingleMockPropertyTypeRector extends AbstractRector
22+
final class SingleMockPropertyTypeRector extends AbstractRector implements ComposerPackageConstraintInterface
2123
{
2224
public function __construct(
2325
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
2426
) {
2527
}
2628

29+
public function provideComposerPackageConstraint(): ComposerPackageConstraint
30+
{
31+
return new ComposerPackageConstraint('phpunit/phpunit', '>=11.0');
32+
}
33+
2734
public function getRuleDefinition(): RuleDefinition
2835
{
2936
return new RuleDefinition(

rules/PHPUnit100/Rector/Class_/AddProphecyTraitRector.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@
1414
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
1515
use Rector\Rector\AbstractRector;
1616
use Rector\Reflection\ReflectionResolver;
17+
use Rector\VersionBonding\Contract\ComposerPackageConstraintInterface;
18+
use Rector\VersionBonding\ValueObject\ComposerPackageConstraint;
1719
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1820
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
1921

2022
/**
23+
* The ProphecyTrait is provided by the "phpspec/prophecy-phpunit" package since its 1.0 version,
24+
* as prophecy was removed from PHPUnit itself
25+
*
2126
* @changelog https://github.com/sebastianbergmann/phpunit/issues/4142
2227
* @changelog https://github.com/sebastianbergmann/phpunit/issues/4141
2328
* @changelog https://github.com/sebastianbergmann/phpunit/issues/4149
2429
*
2530
* @see \Rector\PHPUnit\Tests\PHPUnit100\Rector\Class_\AddProphecyTraitRector\AddProphecyTraitRectorTest
2631
*/
27-
final class AddProphecyTraitRector extends AbstractRector
32+
final class AddProphecyTraitRector extends AbstractRector implements ComposerPackageConstraintInterface
2833
{
2934
public function __construct(
3035
private readonly TestsNodeAnalyzer $testsNodeAnalyzer,
@@ -33,6 +38,11 @@ public function __construct(
3338
) {
3439
}
3540

41+
public function provideComposerPackageConstraint(): ComposerPackageConstraint
42+
{
43+
return new ComposerPackageConstraint('phpspec/prophecy-phpunit', '>=1.0');
44+
}
45+
3646
public function getRuleDefinition(): RuleDefinition
3747
{
3848
return new RuleDefinition(

0 commit comments

Comments
 (0)