Updated Rector to commit 29c634ff65

29c634ff65 [Php74] Add inlinePublic configurable for TypedPropertyRector (#1745)
This commit is contained in:
Tomas Votruba 2022-02-02 21:14:38 +00:00
parent 7764769219
commit 6695b021a0
19 changed files with 129 additions and 711 deletions

View File

@ -1,4 +1,4 @@
# 520 Rules Overview
# 521 Rules Overview
<br>
@ -38,7 +38,7 @@
- [DowngradePhp74](#downgradephp74) (12)
- [DowngradePhp80](#downgradephp80) (27)
- [DowngradePhp80](#downgradephp80) (28)
- [DowngradePhp81](#downgradephp81) (8)
@ -5746,6 +5746,33 @@ Downgrade `str_starts_with()` to `strncmp()` version
<br>
### DowngradeStringReturnTypeOnToStringRector
Add "string" return on current `__toString()` method when parent method has string return on `__toString()` method
- class: [`Rector\DowngradePhp80\Rector\ClassMethod\DowngradeStringReturnTypeOnToStringRector`](../rules/DowngradePhp80/Rector/ClassMethod/DowngradeStringReturnTypeOnToStringRector.php)
```diff
abstract class ParentClass
{
public function __toString(): string
{
return 'value';
}
}
class ChildClass extends ParentClass
{
- public function __toString()
+ public function __toString(): string
{
return 'value';
}
}
```
<br>
### DowngradeThrowExprRector
Downgrade throw expression
@ -8040,8 +8067,26 @@ Add null default to properties with PHP 7.4 property nullable type
Changes property `@var` annotations from annotation to type.
:wrench: **configure it!**
- class: [`Rector\Php74\Rector\Property\TypedPropertyRector`](../rules/Php74/Rector/Property/TypedPropertyRector.php)
```php
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(TypedPropertyRector::class)
->configure([
TypedPropertyRector::INLINE_PUBLIC => false,
]);
};
```
```diff
final class SomeClass
{

View File

@ -17,6 +17,7 @@ use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface;
use Rector\Core\NodeAnalyzer\PropertyAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\PhpParser\AstResolver;
@ -31,7 +32,7 @@ use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\TypeDeclaration\TypeInferer\VarDocPropertyTypeInferer;
use Rector\VendorLocker\VendorLockResolver;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/typed_properties_v2#proposal
@ -41,8 +42,22 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
* @see \Rector\Tests\Php74\Rector\Property\TypedPropertyRector\DoctrineTypedPropertyRectorTest
* @see \Rector\Tests\Php74\Rector\Property\TypedPropertyRector\ImportedTest
*/
final class TypedPropertyRector extends \Rector\Core\Rector\AbstractRector implements \Rector\VersionBonding\Contract\MinPhpVersionInterface
final class TypedPropertyRector extends \Rector\Core\Rector\AbstractRector implements \Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface, \Rector\VersionBonding\Contract\MinPhpVersionInterface
{
/**
* @var string
*/
public const INLINE_PUBLIC = 'inline_public';
/**
* Default to false, which only apply changes:
*
* private modifier property
* - protected modifier property on final class without extends
*
* Set to true will allow change other modifiers as well as far as not forbidden, eg: callable type, null type, etc.
* @var bool
*/
private $inlinePublic = \false;
/**
* @readonly
* @var \Rector\TypeDeclaration\TypeInferer\VarDocPropertyTypeInferer
@ -100,9 +115,13 @@ final class TypedPropertyRector extends \Rector\Core\Rector\AbstractRector imple
$this->astResolver = $astResolver;
$this->objectTypeAnalyzer = $objectTypeAnalyzer;
}
public function configure(array $configuration) : void
{
$this->inlinePublic = $configuration[self::INLINE_PUBLIC] ?? (bool) \current($configuration);
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Changes property `@var` annotations from annotation to type.', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Changes property `@var` annotations from annotation to type.', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample(<<<'CODE_SAMPLE'
final class SomeClass
{
/**
@ -117,7 +136,7 @@ final class SomeClass
private int $count;
}
CODE_SAMPLE
)]);
, [self::INLINE_PUBLIC => \false])]);
}
/**
* @return array<class-string<Node>>
@ -240,6 +259,9 @@ CODE_SAMPLE
if ($this->isModifiedByTrait($class, $propertyName)) {
return \true;
}
if ($this->inlinePublic) {
return $this->propertyAnalyzer->hasForbiddenType($property);
}
if ($property->isPrivate()) {
return $this->propertyAnalyzer->hasForbiddenType($property);
}

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = '8320d290031d91d232e3dd5b1b8779fbcb6e5a07';
public const PACKAGE_VERSION = '29c634ff653949ecd66154409d0e86c6d5f78876';
/**
* @var string
*/
public const RELEASE_DATE = '2022-02-02 10:05:09';
public const RELEASE_DATE = '2022-02-02 22:06:51';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20220202\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe::getLoader();
return ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df::getLoader();

View File

@ -2463,12 +2463,10 @@ return array(
'Rector\\PHPStanStaticTypeMapper\\Utils\\TypeUnwrapper' => $baseDir . '/packages/PHPStanStaticTypeMapper/Utils/TypeUnwrapper.php',
'Rector\\PHPStanStaticTypeMapper\\ValueObject\\UnionTypeAnalysis' => $baseDir . '/packages/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php',
'Rector\\PHPUnit\\Naming\\TestClassNameResolver' => $vendorDir . '/rector/rector-phpunit/src/Naming/TestClassNameResolver.php',
'Rector\\PHPUnit\\NodeAnalyzer\\ExpectationAnalyzer' => $vendorDir . '/rector/rector-phpunit/src/NodeAnalyzer/ExpectationAnalyzer.php',
'Rector\\PHPUnit\\NodeAnalyzer\\IdentifierManipulator' => $vendorDir . '/rector/rector-phpunit/src/NodeAnalyzer/IdentifierManipulator.php',
'Rector\\PHPUnit\\NodeAnalyzer\\TestsNodeAnalyzer' => $vendorDir . '/rector/rector-phpunit/src/NodeAnalyzer/TestsNodeAnalyzer.php',
'Rector\\PHPUnit\\NodeFactory\\ArgumentShiftingFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/ArgumentShiftingFactory.php',
'Rector\\PHPUnit\\NodeFactory\\AssertCallFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/AssertCallFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ConsecutiveAssertionFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/ConsecutiveAssertionFactory.php',
'Rector\\PHPUnit\\NodeFactory\\DataProviderClassMethodFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/DataProviderClassMethodFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ExpectExceptionCodeFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/ExpectExceptionCodeFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ExpectExceptionFactory' => $vendorDir . '/rector/rector-phpunit/src/NodeFactory/ExpectExceptionFactory.php',
@ -2483,7 +2481,6 @@ return array(
'Rector\\PHPUnit\\PhpDoc\\PhpDocValueToNodeMapper' => $vendorDir . '/rector/rector-phpunit/src/PhpDoc/PhpDocValueToNodeMapper.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\AddDoesNotPerformAssertionToNonAssertingTestRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\ExceptionAnnotationRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/ClassMethod/ExceptionAnnotationRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\MigrateAtToConsecutiveExpectationsRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/ClassMethod/MigrateAtToConsecutiveExpectationsRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\RemoveEmptyTestMethodRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/ClassMethod/RemoveEmptyTestMethodRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\TryCatchToExpectExceptionRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/ClassMethod/TryCatchToExpectExceptionRector.php',
'Rector\\PHPUnit\\Rector\\Class_\\AddProphecyTraitRector' => $vendorDir . '/rector/rector-phpunit/src/Rector/Class_/AddProphecyTraitRector.php',
@ -2526,8 +2523,6 @@ return array(
'Rector\\PHPUnit\\ValueObject\\BinaryOpWithAssertMethod' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/BinaryOpWithAssertMethod.php',
'Rector\\PHPUnit\\ValueObject\\ConstantWithAssertMethods' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/ConstantWithAssertMethods.php',
'Rector\\PHPUnit\\ValueObject\\DataProviderClassMethodRecipe' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/DataProviderClassMethodRecipe.php',
'Rector\\PHPUnit\\ValueObject\\ExpectationMock' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/ExpectationMock.php',
'Rector\\PHPUnit\\ValueObject\\ExpectationMockCollection' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/ExpectationMockCollection.php',
'Rector\\PHPUnit\\ValueObject\\FunctionNameWithAssertMethods' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/FunctionNameWithAssertMethods.php',
'Rector\\PHPUnit\\ValueObject\\ParamAndArg' => $vendorDir . '/rector/rector-phpunit/src/ValueObject/ParamAndArg.php',
'Rector\\PSR4\\Composer\\PSR4AutoloadPathsProvider' => $baseDir . '/rules/PSR4/Composer/PSR4AutoloadPathsProvider.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe
class ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInita9432eadaa336def2b08e78cb934fdfe::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,12 +42,12 @@ class ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInita9432eadaa336def2b08e78cb934fdfe::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequirea9432eadaa336def2b08e78cb934fdfe($fileIdentifier, $file);
composerRequire2f4bc168891e1f9900b381a90a4fa8df($fileIdentifier, $file);
}
return $loader;
@ -59,7 +59,7 @@ class ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe
* @param string $file
* @return void
*/
function composerRequirea9432eadaa336def2b08e78cb934fdfe($fileIdentifier, $file)
function composerRequire2f4bc168891e1f9900b381a90a4fa8df($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInita9432eadaa336def2b08e78cb934fdfe
class ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@ -2853,12 +2853,10 @@ class ComposerStaticInita9432eadaa336def2b08e78cb934fdfe
'Rector\\PHPStanStaticTypeMapper\\Utils\\TypeUnwrapper' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/Utils/TypeUnwrapper.php',
'Rector\\PHPStanStaticTypeMapper\\ValueObject\\UnionTypeAnalysis' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/ValueObject/UnionTypeAnalysis.php',
'Rector\\PHPUnit\\Naming\\TestClassNameResolver' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Naming/TestClassNameResolver.php',
'Rector\\PHPUnit\\NodeAnalyzer\\ExpectationAnalyzer' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeAnalyzer/ExpectationAnalyzer.php',
'Rector\\PHPUnit\\NodeAnalyzer\\IdentifierManipulator' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeAnalyzer/IdentifierManipulator.php',
'Rector\\PHPUnit\\NodeAnalyzer\\TestsNodeAnalyzer' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeAnalyzer/TestsNodeAnalyzer.php',
'Rector\\PHPUnit\\NodeFactory\\ArgumentShiftingFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/ArgumentShiftingFactory.php',
'Rector\\PHPUnit\\NodeFactory\\AssertCallFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/AssertCallFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ConsecutiveAssertionFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/ConsecutiveAssertionFactory.php',
'Rector\\PHPUnit\\NodeFactory\\DataProviderClassMethodFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/DataProviderClassMethodFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ExpectExceptionCodeFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/ExpectExceptionCodeFactory.php',
'Rector\\PHPUnit\\NodeFactory\\ExpectExceptionFactory' => __DIR__ . '/..' . '/rector/rector-phpunit/src/NodeFactory/ExpectExceptionFactory.php',
@ -2873,7 +2871,6 @@ class ComposerStaticInita9432eadaa336def2b08e78cb934fdfe
'Rector\\PHPUnit\\PhpDoc\\PhpDocValueToNodeMapper' => __DIR__ . '/..' . '/rector/rector-phpunit/src/PhpDoc/PhpDocValueToNodeMapper.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\AddDoesNotPerformAssertionToNonAssertingTestRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\ExceptionAnnotationRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/ClassMethod/ExceptionAnnotationRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\MigrateAtToConsecutiveExpectationsRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/ClassMethod/MigrateAtToConsecutiveExpectationsRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\RemoveEmptyTestMethodRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/ClassMethod/RemoveEmptyTestMethodRector.php',
'Rector\\PHPUnit\\Rector\\ClassMethod\\TryCatchToExpectExceptionRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/ClassMethod/TryCatchToExpectExceptionRector.php',
'Rector\\PHPUnit\\Rector\\Class_\\AddProphecyTraitRector' => __DIR__ . '/..' . '/rector/rector-phpunit/src/Rector/Class_/AddProphecyTraitRector.php',
@ -2916,8 +2913,6 @@ class ComposerStaticInita9432eadaa336def2b08e78cb934fdfe
'Rector\\PHPUnit\\ValueObject\\BinaryOpWithAssertMethod' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/BinaryOpWithAssertMethod.php',
'Rector\\PHPUnit\\ValueObject\\ConstantWithAssertMethods' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/ConstantWithAssertMethods.php',
'Rector\\PHPUnit\\ValueObject\\DataProviderClassMethodRecipe' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/DataProviderClassMethodRecipe.php',
'Rector\\PHPUnit\\ValueObject\\ExpectationMock' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/ExpectationMock.php',
'Rector\\PHPUnit\\ValueObject\\ExpectationMockCollection' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/ExpectationMockCollection.php',
'Rector\\PHPUnit\\ValueObject\\FunctionNameWithAssertMethods' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/FunctionNameWithAssertMethods.php',
'Rector\\PHPUnit\\ValueObject\\ParamAndArg' => __DIR__ . '/..' . '/rector/rector-phpunit/src/ValueObject/ParamAndArg.php',
'Rector\\PSR4\\Composer\\PSR4AutoloadPathsProvider' => __DIR__ . '/../..' . '/rules/PSR4/Composer/PSR4AutoloadPathsProvider.php',
@ -3869,9 +3864,9 @@ class ComposerStaticInita9432eadaa336def2b08e78cb934fdfe
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInita9432eadaa336def2b08e78cb934fdfe::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInita9432eadaa336def2b08e78cb934fdfe::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInita9432eadaa336def2b08e78cb934fdfe::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit2f4bc168891e1f9900b381a90a4fa8df::$classMap;
}, null, ClassLoader::class);
}

View File

@ -1012,17 +1012,17 @@
},
{
"name": "phpstan\/phpstan",
"version": "1.4.4",
"version_normalized": "1.4.4.0",
"version": "1.4.5",
"version_normalized": "1.4.5.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpstan.git",
"reference": "f7409da1e26c6dee172cce744034b869a2f27a9e"
"reference": "150d1fbd82fb71ff76b3bd7f6ea6006d89c5f0c3"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/f7409da1e26c6dee172cce744034b869a2f27a9e",
"reference": "f7409da1e26c6dee172cce744034b869a2f27a9e",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/150d1fbd82fb71ff76b3bd7f6ea6006d89c5f0c3",
"reference": "150d1fbd82fb71ff76b3bd7f6ea6006d89c5f0c3",
"shasum": ""
},
"require": {
@ -1031,7 +1031,7 @@
"conflict": {
"phpstan\/phpstan-shim": "*"
},
"time": "2022-01-31T16:50:49+00:00",
"time": "2022-02-02T19:35:10+00:00",
"bin": [
"phpstan",
"phpstan.phar"
@ -1055,7 +1055,7 @@
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpstan\/issues",
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/1.4.4"
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/1.4.5"
},
"funding": [
{
@ -2522,12 +2522,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
"reference": "5f88c4ba538532cf6b8ee796633cd3e154cd159c"
"reference": "49d312b31dd2eadb8f9bb89a972060b62e1dd063"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/5f88c4ba538532cf6b8ee796633cd3e154cd159c",
"reference": "5f88c4ba538532cf6b8ee796633cd3e154cd159c",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/49d312b31dd2eadb8f9bb89a972060b62e1dd063",
"reference": "49d312b31dd2eadb8f9bb89a972060b62e1dd063",
"shasum": ""
},
"require": {
@ -2551,7 +2551,7 @@
"symplify\/rule-doc-generator": "^10.0",
"symplify\/vendor-patches": "^10.0"
},
"time": "2022-02-01T09:05:58+00:00",
"time": "2022-02-02T20:36:05+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,16 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmH4E2kACgkQzxoQjQ56
5yDoBw/+LOU99QnMCJHXvMbg+oBzc8FkBH/Q+ZBYg+XWbQyBaSohluEbGQtuLdoX
lMIMverJHQ79JCg8PSKpgD0gy94HvgYsK9dbKF6JEJ1G6hrtXTD9FBrIHlW/8yKD
N/IAXx8UYdFEfT5rc+fuSI6JVRDmGssM66UXBKnsNGmc2Iur3AJvSLhPCygRGkRw
GjRpAVqRz4MYT2BC+yF5j5QD6X6BvXLTUaGNdCkoMuMrRYgXUS18Nmqw5HkyFka2
E0cXThfa+uDlbuY/wd0beLB5RT7QyX7AQwNJTMDXcbdDARMtBtdSG2yTIRW3VsGO
Q0gtw5UhIvGTVyEZuBdTAI3xhmFR0ehZBi7lnn7qN6EbAvaHLpGW9WhIQuEvw3SY
VZmnVrNl/ioyMUH6OWeKjVwmBngVWdlrjibVHP0f+PqD2nU1pNgjkRm1aEBbPQ+g
dNB3uxKDW0qJECXpSm9zC9TRzvw695Oo5qxD+Vx2wOlaKzUBQfBvQRhza+tpDVwq
Y0GTZy/jYNl8PM7sRXKOrQqFV7OzuJNrZUzTsZ31gCAC3QqcNiF+OeuZB58KB/Va
Txz1r6EOOdm+pkKEfGouOzONpd7P3jv4fA6drpoIvfhUQ9fNcnLSJnf0pOuMmIgl
AGtPDu1f4IufnwUwh0/JhwHLW/BEmPfZt55XDaYII20z2/aW708=
=GoKy
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmH63O0ACgkQzxoQjQ56
5yAGLw//XoKgrdDKO3XKrSlO8NjLC8TQcCqPX2KFbCEhIUC4HXilbjZHsyIsBnSC
VPbyWDKk5f2ugSq6/8zwdvD6VP3JGbP/4sGUxm9Y0N3EojPOEwQXueR1cRMo3EGx
fyzqRMgBJSGr43cSmokv5/mA6QpMWCtlxbMBP+g3t09MwA5ywDL/SylN+k0hXEAx
D5u/lhs+EtZ+q978CUDla1Sf2gToKnli00i3mHTLQMDs/cHQ+gVUXcLjFbIOMbW8
n2+Jp5Y2a/zRCkTgxhfuV9FWj4F43Qu00qAsfzDlltbG55ks7DcLONldP/7Qg9uN
ODiIO6fu3v7oqy4hg3lqeNPwCtNk5Gz9r6rjfuvCA2t/QDnOOIad1X3nPTxfb1i+
UyVjg3/pfLmYmhtEF48jkN6dm8TAPV2HTdv5E8bhzKbxVu/YVcRmXQOnnMs+cNAj
nU3z+SU2wxfnZH50Qw7QILEUIKpm8AfinbA5V1q1hvKsNOTsPZamYYeHvnCqdhDh
0VLFCTrD2j6Azu6CLnf8fqegXdZlEUqkuhgJ8OyZW3Mtuy5RxkYbCUCnMUnTLN5x
Ddz56sx5I0eqqnVIBPhorhZxKZLVaguEAjSuxX4WaaRiUKno7rYzojyFo0pyVa0M
rRd4hlg4bLMk+GRS3fyCZr8mQhb24AzvXTdRhAYg8WdfFTaogeM=
=Gtro
-----END PGP SIGNATURE-----

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main d1fa93d'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main fbac1ab'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main df58e86'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 6bee428'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main fbfa93c'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main f23c4bf'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 5f88c4b'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 57743a8'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 9c08a83'));
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main d1fa93d'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main fbac1ab'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main df58e86'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 6bee428'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main fbfa93c'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main f23c4bf'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 49d312b'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 57743a8'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 9c08a83'));
private function __construct()
{
}

View File

@ -1,4 +1,4 @@
# 39 Rules Overview
# 38 Rules Overview
## AddDoesNotPerformAssertionToNonAssertingTestRector
@ -87,11 +87,16 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ArrayArgumentToDataProviderRector::class)
->configure([
ArrayArgumentToDataProviderRector::ARRAY_ARGUMENTS_TO_DATA_PROVIDERS => ValueObjectInliner::inline([
new ArrayArgumentToDataProvider('PHPUnit\Framework\TestCase', 'doTestMultiple', 'doTestSingle', 'number'),
]),
]]);
->call('configure', [[
ArrayArgumentToDataProviderRector::ARRAY_ARGUMENTS_TO_DATA_PROVIDERS => ValueObjectInliner::inline([
new ArrayArgumentToDataProvider(
'PHPUnit\Framework\TestCase',
'doTestMultiple',
'doTestSingle',
'number'
),
]),
]]);
};
```
@ -579,21 +584,6 @@ Turns getMock*() methods to `createMock()`
<br>
## MigrateAtToConsecutiveExpectationsRector
Migrates deprecated `$this->at` to `$this->withConsecutive` and `$this->willReturnOnConsecutiveCalls`
- class: [`Rector\PHPUnit\Rector\ClassMethod\MigrateAtToConsecutiveExpectationsRector`](../src/Rector/ClassMethod/MigrateAtToConsecutiveExpectationsRector.php)
```diff
$mock = $this->createMock(Foo::class);
-$mock->expects($this->at(0))->with('0')->method('someMethod')->willReturn('1');
-$mock->expects($this->at(1))->with('1')->method('someMethod')->willReturn('2');
+$mock->method('someMethod')->withConsecutive(['0'], ['1'])->willReturnOnConsecutiveCalls('1', '2');
```
<br>
## RemoveDataProviderTestPrefixRector
Data provider methods cannot start with "test" prefix

View File

@ -1,133 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\PHPUnit\NodeAnalyzer;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\Expression;
use Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory;
use Rector\PHPUnit\ValueObject\ExpectationMock;
use Rector\PHPUnit\ValueObject\ExpectationMockCollection;
final class ExpectationAnalyzer
{
/**
* @var string[]
*/
private const PROCESSABLE_WILL_STATEMENTS = ['will', 'willReturn', 'willReturnReference', 'willReturnMap', 'willReturnArgument', 'willReturnCallback', 'willReturnSelf', 'willThrowException'];
/**
* @readonly
* @var \Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer
*/
private $testsNodeAnalyzer;
/**
* @readonly
* @var \Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory
*/
private $consecutiveAssertionFactory;
public function __construct(\Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer $testsNodeAnalyzer, \Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory $consecutiveAssertionFactory)
{
$this->testsNodeAnalyzer = $testsNodeAnalyzer;
$this->consecutiveAssertionFactory = $consecutiveAssertionFactory;
}
/**
* @param Expression[] $stmts
*/
public function getExpectationsFromExpressions(array $stmts) : \Rector\PHPUnit\ValueObject\ExpectationMockCollection
{
$expectationMockCollection = new \Rector\PHPUnit\ValueObject\ExpectationMockCollection();
foreach ($stmts as $stmt) {
/** @var MethodCall $expr */
$expr = $stmt->expr;
$method = $this->getMethod($expr);
if (!$this->testsNodeAnalyzer->isInPHPUnitMethodCallName($method, 'method')) {
continue;
}
/** @var MethodCall $expects */
$expects = $this->getExpects($method->var, $method);
if (!$this->isValidExpectsCall($expects)) {
continue;
}
$expectsArg = $expects->getArgs()[0];
$expectsValue = $expectsArg->value;
if (!$this->isValidAtCall($expectsValue)) {
continue;
}
/** @var MethodCall|StaticCall $expectsValue */
$atArg = $expectsValue->getArgs()[0];
$atValue = $atArg->value;
if (!$atValue instanceof \PhpParser\Node\Scalar\LNumber) {
continue;
}
if (!$expects->var instanceof \PhpParser\Node\Expr\Variable && !$expects->var instanceof \PhpParser\Node\Expr\PropertyFetch) {
continue;
}
$expectationMockCollection->add(new \Rector\PHPUnit\ValueObject\ExpectationMock($expects->var, $method->args, $atValue->value, $this->getWill($expr), $this->getWithArgs($method->var), $stmt));
}
return $expectationMockCollection;
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $call
*/
public function isValidExpectsCall($call) : bool
{
if (!$this->testsNodeAnalyzer->isInPHPUnitMethodCallName($call, 'expects')) {
return \false;
}
return \count($call->getArgs()) === 1;
}
public function isValidAtCall(\PhpParser\Node\Expr $expr) : bool
{
if (!$expr instanceof \PhpParser\Node\Expr\StaticCall && !$expr instanceof \PhpParser\Node\Expr\MethodCall) {
return \false;
}
if (!$this->testsNodeAnalyzer->isInPHPUnitMethodCallName($expr, 'at')) {
return \false;
}
return \count($expr->getArgs()) === 1;
}
private function getMethod(\PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr\MethodCall
{
if ($this->testsNodeAnalyzer->isPHPUnitMethodCallNames($methodCall, self::PROCESSABLE_WILL_STATEMENTS) && $methodCall->var instanceof \PhpParser\Node\Expr\MethodCall) {
return $methodCall->var;
}
return $methodCall;
}
private function getWill(\PhpParser\Node\Expr\MethodCall $methodCall) : ?\PhpParser\Node\Expr
{
if (!$this->testsNodeAnalyzer->isPHPUnitMethodCallNames($methodCall, self::PROCESSABLE_WILL_STATEMENTS)) {
return null;
}
return $this->consecutiveAssertionFactory->createWillReturn($methodCall);
}
private function getExpects(\PhpParser\Node\Expr $expr, \PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr
{
if (!$expr instanceof \PhpParser\Node\Expr\MethodCall) {
return $methodCall;
}
if (!$this->testsNodeAnalyzer->isInPHPUnitMethodCallName($expr, 'with')) {
return $methodCall->var;
}
return $expr->var;
}
/**
* @return array<int, Expr|null>
*/
private function getWithArgs(\PhpParser\Node\Expr $expr) : array
{
if (!$this->testsNodeAnalyzer->isInPHPUnitMethodCallName($expr, 'with')) {
return [null];
}
if (!$expr instanceof \PhpParser\Node\Expr\MethodCall) {
return [null];
}
return \array_map(static function (\PhpParser\Node\Arg $arg) : Expr {
return $arg->value;
}, $expr->args);
}
}

View File

@ -1,133 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\PHPUnit\NodeFactory;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use Rector\PHPUnit\ValueObject\ExpectationMock;
use Rector\PHPUnit\ValueObject\ExpectationMockCollection;
final class ConsecutiveAssertionFactory
{
/**
* @var array<string, string>
*/
private const REPLACE_WILL_MAP = ['willReturnMap' => 'returnValueMap', 'willReturnArgument' => 'returnArgument', 'willReturnCallback' => 'returnCallback', 'willThrowException' => 'throwException'];
public function createAssertionFromExpectationMockCollection(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : \PhpParser\Node\Expr\MethodCall
{
$expectationMocks = $expectationMockCollection->getExpectationMocks();
$variable = $expectationMocks[0]->getExpectationVariable();
$methodArguments = $expectationMocks[0]->getMethodArguments();
$expectationMocks = $this->sortExpectationMocksByIndex($expectationMocks);
if (!$expectationMockCollection->hasReturnValues()) {
return $this->createWithConsecutive($this->createMethod($variable, $methodArguments), $this->createWithArgs($expectationMocks));
}
if ($expectationMockCollection->hasWithValues()) {
return $this->createWillReturnOnConsecutiveCalls($this->createWithConsecutive($this->createMethod($variable, $methodArguments), $this->createWithArgs($expectationMocks)), $this->createReturnArgs($expectationMocks));
}
return $this->createWillReturnOnConsecutiveCalls($this->createMethod($variable, $methodArguments), $this->createReturnArgs($expectationMocks));
}
/**
* @param Arg[] $args
*/
public function createWillReturnOnConsecutiveCalls(\PhpParser\Node\Expr $expr, array $args) : \PhpParser\Node\Expr\MethodCall
{
return $this->createMethodCall($expr, 'willReturnOnConsecutiveCalls', $args);
}
/**
* @param Arg[] $args
*/
public function createMethod(\PhpParser\Node\Expr $expr, array $args) : \PhpParser\Node\Expr\MethodCall
{
return $this->createMethodCall($expr, 'method', $args);
}
/**
* @param Arg[] $args
*/
public function createWithConsecutive(\PhpParser\Node\Expr $expr, array $args) : \PhpParser\Node\Expr\MethodCall
{
return $this->createMethodCall($expr, 'withConsecutive', $args);
}
public function createWillReturn(\PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr
{
if (!$methodCall->name instanceof \PhpParser\Node\Identifier) {
return $methodCall;
}
$methodCallName = $methodCall->name->name;
if ($methodCallName === 'will') {
return $methodCall->args[0]->value;
}
if ($methodCallName === 'willReturnSelf') {
return $this->createWillReturnSelf();
}
if ($methodCallName === 'willReturnReference') {
return $this->createWillReturnReference($methodCall);
}
if (\array_key_exists($methodCallName, self::REPLACE_WILL_MAP)) {
return $this->createMappedWillReturn($methodCallName, $methodCall);
}
return $methodCall->args[0]->value;
}
/**
* @param ExpectationMock[] $expectationMocks
* @return Arg[]
*/
private function createReturnArgs(array $expectationMocks) : array
{
return \array_map(static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : Arg {
return new \PhpParser\Node\Arg($expectationMock->getReturn() instanceof \PhpParser\Node\Expr ? $expectationMock->getReturn() : new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('null')));
}, $expectationMocks);
}
/**
* @param ExpectationMock[] $expectationMocks
* @return Arg[]
*/
private function createWithArgs(array $expectationMocks) : array
{
return \array_map(static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : Arg {
$arrayItems = \array_map(static function (?\PhpParser\Node\Expr $expr) : ArrayItem {
return new \PhpParser\Node\Expr\ArrayItem($expr instanceof \PhpParser\Node\Expr ? $expr : new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('null')));
}, $expectationMock->getWithArguments());
return new \PhpParser\Node\Arg(new \PhpParser\Node\Expr\Array_($arrayItems));
}, $expectationMocks);
}
private function createWillReturnSelf() : \PhpParser\Node\Expr\MethodCall
{
return $this->createMethodCall(new \PhpParser\Node\Expr\Variable('this'), 'returnSelf', []);
}
private function createWillReturnReference(\PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr\New_
{
return new \PhpParser\Node\Expr\New_(new \PhpParser\Node\Name\FullyQualified('PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference'), [new \PhpParser\Node\Arg($methodCall->args[0]->value)]);
}
private function createMappedWillReturn(string $methodCallName, \PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr\MethodCall
{
return $this->createMethodCall(new \PhpParser\Node\Expr\Variable('this'), self::REPLACE_WILL_MAP[$methodCallName], [new \PhpParser\Node\Arg($methodCall->args[0]->value)]);
}
/**
* @param Arg[] $args
*/
private function createMethodCall(\PhpParser\Node\Expr $expr, string $name, array $args) : \PhpParser\Node\Expr\MethodCall
{
return new \PhpParser\Node\Expr\MethodCall($expr, new \PhpParser\Node\Identifier($name), $args);
}
/**
* @param ExpectationMock[] $expectationMocks
* @return ExpectationMock[]
*/
private function sortExpectationMocksByIndex(array $expectationMocks) : array
{
\usort($expectationMocks, static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMockA, \Rector\PHPUnit\ValueObject\ExpectationMock $expectationMockB) : int {
return $expectationMockA->getIndex() > $expectationMockB->getIndex() ? 1 : -1;
});
return $expectationMocks;
}
}

View File

@ -1,162 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\PHPUnit\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Rector\AbstractRector;
use Rector\PHPUnit\NodeAnalyzer\ExpectationAnalyzer;
use Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory;
use Rector\PHPUnit\ValueObject\ExpectationMock;
use Rector\PHPUnit\ValueObject\ExpectationMockCollection;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\PHPUnit\Tests\Rector\ClassMethod\MigrateAtToConsecutiveExpectationsRector\MigrateAtToConsecutiveExpectationsRectorTest
*/
final class MigrateAtToConsecutiveExpectationsRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @readonly
* @var \Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory
*/
private $consecutiveAssertionFactory;
/**
* @readonly
* @var \Rector\PHPUnit\NodeAnalyzer\ExpectationAnalyzer
*/
private $expectationAnalyzer;
public function __construct(\Rector\PHPUnit\NodeFactory\ConsecutiveAssertionFactory $consecutiveAssertionFactory, \Rector\PHPUnit\NodeAnalyzer\ExpectationAnalyzer $expectationAnalyzer)
{
$this->consecutiveAssertionFactory = $consecutiveAssertionFactory;
$this->expectationAnalyzer = $expectationAnalyzer;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Migrates deprecated $this->at to $this->withConsecutive and $this->willReturnOnConsecutiveCalls', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
$mock = $this->createMock(Foo::class);
$mock->expects($this->at(0))->with('0')->method('someMethod')->willReturn('1');
$mock->expects($this->at(1))->with('1')->method('someMethod')->willReturn('2');
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$mock = $this->createMock(Foo::class);
$mock->method('someMethod')->withConsecutive(['0'], ['1'])->willReturnOnConsecutiveCalls('1', '2');
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\ClassMethod::class];
}
/**
* @param ClassMethod $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
$stmts = $node->stmts;
if ($stmts === null) {
return null;
}
$expressions = \array_filter($stmts, function (\PhpParser\Node\Stmt $expr) : bool {
return $expr instanceof \PhpParser\Node\Stmt\Expression && $expr->expr instanceof \PhpParser\Node\Expr\MethodCall;
});
$expectationMockCollection = $this->expectationAnalyzer->getExpectationsFromExpressions($expressions);
if (!$expectationMockCollection->hasExpectationMocks()) {
return null;
}
$expectationCollections = $this->groupExpectationCollectionsByVariableName($expectationMockCollection);
foreach ($expectationCollections as $expectationCollection) {
$this->replaceExpectationNodes($expectationCollection);
}
return $node;
}
private function buildNewExpectation(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : \PhpParser\Node\Expr\MethodCall
{
$this->fillMissingAtIndexes($expectationMockCollection);
return $this->consecutiveAssertionFactory->createAssertionFromExpectationMockCollection($expectationMockCollection);
}
private function fillMissingAtIndexes(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : void
{
$variable = $expectationMockCollection->getExpectationMocks()[0]->getExpectationVariable();
// OR
if ($expectationMockCollection->getLowestAtIndex() !== 0) {
for ($i = 0; $i < $expectationMockCollection->getLowestAtIndex(); ++$i) {
$expectationMockCollection->add(new \Rector\PHPUnit\ValueObject\ExpectationMock($variable, [], $i, null, [], null));
}
}
if ($expectationMockCollection->isMissingAtIndexBetweenHighestAndLowest()) {
$existingIndexes = \array_column($expectationMockCollection->getExpectationMocks(), 'index');
for ($i = 1; $i < $expectationMockCollection->getHighestAtIndex(); ++$i) {
if (!\in_array($i, $existingIndexes, \true)) {
$expectationMockCollection->add(new \Rector\PHPUnit\ValueObject\ExpectationMock($variable, [], $i, null, [], null));
}
}
}
}
private function replaceExpectationNodes(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : void
{
if ($this->shouldSkipReplacement($expectationMockCollection)) {
return;
}
$endLines = \array_map(static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : int {
$originalExpression = $expectationMock->getOriginalExpression();
return $originalExpression instanceof \PhpParser\Node\Stmt\Expression ? $originalExpression->getEndLine() : 0;
}, $expectationMockCollection->getExpectationMocks());
$max = \max($endLines);
foreach ($expectationMockCollection->getExpectationMocks() as $expectationMock) {
$originalExpression = $expectationMock->getOriginalExpression();
if (!$originalExpression instanceof \PhpParser\Node\Stmt\Expression) {
continue;
}
if ($max > $originalExpression->getEndLine()) {
$this->removeNode($originalExpression);
} else {
$originalExpression->expr = $this->buildNewExpectation($expectationMockCollection);
}
}
}
private function shouldSkipReplacement(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : bool
{
if (!$expectationMockCollection->hasReturnValues()) {
return \false;
}
if (!$expectationMockCollection->isExpectedMethodAlwaysTheSame()) {
return \true;
}
if ($expectationMockCollection->hasMissingAtIndexes()) {
return \true;
}
return $expectationMockCollection->hasMissingReturnValues();
}
/**
* @return ExpectationMockCollection[]
*/
private function groupExpectationCollectionsByVariableName(\Rector\PHPUnit\ValueObject\ExpectationMockCollection $expectationMockCollection) : array
{
$groupedByVariable = [];
foreach ($expectationMockCollection->getExpectationMocks() as $expectationMock) {
$variable = $expectationMock->getExpectationVariable();
// The $variable->name will be a string if the mock object is stored as a local variable (Expr\Variable)
// The $variable->name will be Identifier object when the mock object is stored as a class property (Expr\PropertyFetch).
if ($variable->name instanceof \PhpParser\Node\Identifier) {
$variable = $variable->name;
}
if (!\is_string($variable->name)) {
continue;
}
if (!isset($groupedByVariable[$variable->name])) {
$groupedByVariable[$variable->name] = new \Rector\PHPUnit\ValueObject\ExpectationMockCollection();
}
$groupedByVariable[$variable->name]->add($expectationMock);
}
return \array_values($groupedByVariable);
}
}

View File

@ -1,90 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\PHPUnit\ValueObject;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
final class ExpectationMock
{
/**
* @var Variable|PropertyFetch
* @readonly
*/
private $expectationVariable;
/**
* @var Arg[]
* @readonly
*/
private $methodArguments;
/**
* @readonly
* @var int
*/
private $index;
/**
* @readonly
* @var \PhpParser\Node\Expr|null
*/
private $expr;
/**
* @var array<int, (null | Expr)>
* @readonly
*/
private $withArguments;
/**
* @readonly
* @var \PhpParser\Node\Stmt\Expression|null
*/
private $originalExpression;
/**
* @param Variable|PropertyFetch $expectationVariable
* @param Arg[] $methodArguments
* @param array<int, null|Expr> $withArguments
*/
public function __construct(\PhpParser\Node\Expr $expectationVariable, array $methodArguments, int $index, ?\PhpParser\Node\Expr $expr, array $withArguments, ?\PhpParser\Node\Stmt\Expression $originalExpression)
{
$this->expectationVariable = $expectationVariable;
$this->methodArguments = $methodArguments;
$this->index = $index;
$this->expr = $expr;
$this->withArguments = $withArguments;
$this->originalExpression = $originalExpression;
}
/**
* @return Variable|PropertyFetch
*/
public function getExpectationVariable() : \PhpParser\Node\Expr
{
return $this->expectationVariable;
}
/**
* @return Arg[]
*/
public function getMethodArguments() : array
{
return $this->methodArguments;
}
public function getIndex() : int
{
return $this->index;
}
public function getReturn() : ?\PhpParser\Node\Expr
{
return $this->expr;
}
/**
* @return array<int, null|Expr>
*/
public function getWithArguments() : array
{
return $this->withArguments;
}
public function getOriginalExpression() : ?\PhpParser\Node\Stmt\Expression
{
return $this->originalExpression;
}
}

View File

@ -1,111 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\PHPUnit\ValueObject;
use PhpParser\Node\Scalar\String_;
final class ExpectationMockCollection
{
/**
* @var ExpectationMock[]
*/
private $expectationMocks = [];
/**
* @return ExpectationMock[]
*/
public function getExpectationMocks() : array
{
return $this->expectationMocks;
}
public function hasExpectationMocks() : bool
{
return $this->expectationMocks !== [];
}
public function add(\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : void
{
$this->expectationMocks[] = $expectationMock;
}
public function getHighestAtIndex() : int
{
if (!$this->hasExpectationMocks()) {
return 0;
}
$indexes = \array_map(static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : int {
return $expectationMock->getIndex();
}, $this->expectationMocks);
return (int) \max($indexes);
}
public function getLowestAtIndex() : int
{
if (!$this->hasExpectationMocks()) {
return 0;
}
$indexes = \array_map(static function (\Rector\PHPUnit\ValueObject\ExpectationMock $expectationMock) : int {
return $expectationMock->getIndex();
}, $this->expectationMocks);
return (int) \min($indexes);
}
public function isMissingAtIndexBetweenHighestAndLowest() : bool
{
$highestAtIndex = $this->getHighestAtIndex();
$lowestAtIndex = $this->getLowestAtIndex();
return $highestAtIndex - $lowestAtIndex + 1 !== \count($this->expectationMocks);
}
public function hasMissingAtIndexes() : bool
{
if ($this->getLowestAtIndex() !== 0) {
return \true;
}
return $this->isMissingAtIndexBetweenHighestAndLowest();
}
public function hasWithValues() : bool
{
foreach ($this->expectationMocks as $expectationMock) {
if (\count($expectationMock->getWithArguments()) > 1) {
return \true;
}
if (\count($expectationMock->getWithArguments()) !== 1) {
continue;
}
if ($expectationMock->getWithArguments()[0] === null) {
continue;
}
return \true;
}
return \false;
}
public function hasReturnValues() : bool
{
foreach ($this->expectationMocks as $expectationMock) {
if ($expectationMock->getReturn() !== null) {
return \true;
}
}
return \false;
}
public function hasMissingReturnValues() : bool
{
foreach ($this->expectationMocks as $expectationMock) {
if ($expectationMock->getReturn() === null) {
return \true;
}
}
return \false;
}
public function isExpectedMethodAlwaysTheSame() : bool
{
$previousMethod = '';
foreach ($this->expectationMocks as $expectationMock) {
$methodArgument = $expectationMock->getMethodArguments()[0];
if ($methodArgument->value instanceof \PhpParser\Node\Scalar\String_) {
if ($previousMethod === '') {
$previousMethod = $methodArgument->value->value;
}
if ($previousMethod !== $methodArgument->value->value) {
return \false;
}
}
}
return \true;
}
}

View File

@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php';
if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) {
spl_autoload_call('RectorPrefix20220202\AutoloadIncluder');
}
if (!class_exists('ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe', false) && !interface_exists('ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe', false) && !trait_exists('ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe', false)) {
spl_autoload_call('RectorPrefix20220202\ComposerAutoloaderInita9432eadaa336def2b08e78cb934fdfe');
if (!class_exists('ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df', false) && !interface_exists('ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df', false) && !trait_exists('ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df', false)) {
spl_autoload_call('RectorPrefix20220202\ComposerAutoloaderInit2f4bc168891e1f9900b381a90a4fa8df');
}
if (!class_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !interface_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !trait_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false)) {
spl_autoload_call('RectorPrefix20220202\Helmich\TypoScriptParser\Parser\AST\Statement');
@ -71,9 +71,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20220202\print_node(...func_get_args());
}
}
if (!function_exists('composerRequirea9432eadaa336def2b08e78cb934fdfe')) {
function composerRequirea9432eadaa336def2b08e78cb934fdfe() {
return \RectorPrefix20220202\composerRequirea9432eadaa336def2b08e78cb934fdfe(...func_get_args());
if (!function_exists('composerRequire2f4bc168891e1f9900b381a90a4fa8df')) {
function composerRequire2f4bc168891e1f9900b381a90a4fa8df() {
return \RectorPrefix20220202\composerRequire2f4bc168891e1f9900b381a90a4fa8df(...func_get_args());
}
}
if (!function_exists('scanPath')) {