diff --git a/composer.json b/composer.json index 60a6901fda5d..03f157ce1346 100644 --- a/composer.json +++ b/composer.json @@ -72,8 +72,19 @@ "Rector\\PSR4\\": "packages/PSR4/src", "Rector\\PhpSpecToPHPUnit\\": "packages/PhpSpecToPHPUnit/src", "Rector\\Php\\": "packages/Php/src", + "Rector\\Php52\\": "packages/Php52/src", + "Rector\\Php53\\": "packages/Php53/src", + "Rector\\Php54\\": "packages/Php54/src", + "Rector\\Php55\\": "packages/Php55/src", + "Rector\\Php56\\": "packages/Php56/src", + "Rector\\Php70\\": "packages/Php70/src", + "Rector\\Php71\\": "packages/Php71/src", + "Rector\\Php72\\": "packages/Php72/src", + "Rector\\Php73\\": "packages/Php73/src", + "Rector\\Php74\\": "packages/Php74/src", "Rector\\RemovingStatic\\": "packages/RemovingStatic/src", "Rector\\Restoration\\": "packages/Restoration/src", + "Rector\\Refactoring\\": "packages/Refactoring/src", "Rector\\SOLID\\": "packages/SOLID/src", "Rector\\Sensio\\": "packages/Sensio/src", "Rector\\Shopware\\": "packages/Shopware/src", @@ -115,8 +126,19 @@ "Rector\\PHPStan\\Tests\\": "packages/PHPStan/tests", "Rector\\PHPUnitSymfony\\Tests\\": "packages/PHPUnitSymfony/tests", "Rector\\PHPUnit\\Tests\\": "packages/PHPUnit/tests", + "Rector\\PSR4\\Tests\\": "packages/PSR4/tests", "Rector\\PhpSpecToPHPUnit\\Tests\\": "packages/PhpSpecToPHPUnit/tests", "Rector\\Php\\Tests\\": "packages/Php/tests", + "Rector\\Php52\\Tests\\": "packages/Php52/tests", + "Rector\\Php53\\Tests\\": "packages/Php53/tests", + "Rector\\Php54\\Tests\\": "packages/Php54/tests", + "Rector\\Php55\\Tests\\": "packages/Php55/tests", + "Rector\\Php56\\Tests\\": "packages/Php56/tests", + "Rector\\Php70\\Tests\\": "packages/Php70/tests", + "Rector\\Php71\\Tests\\": "packages/Php71/tests", + "Rector\\Php72\\Tests\\": "packages/Php72/tests", + "Rector\\Php73\\Tests\\": "packages/Php73/tests", + "Rector\\Php74\\Tests\\": "packages/Php74/tests", "Rector\\RemovingStatic\\Tests\\": "packages/RemovingStatic/tests", "Rector\\Restoration\\Tests\\": "packages/Restoration/tests", "Rector\\SOLID\\Tests\\": "packages/SOLID/tests", @@ -146,7 +168,7 @@ ], "files": [ "packages/DeadCode/tests/Rector/MethodCall/RemoveDefaultArgumentValueRector/Source/UserDefined.php", - "packages/Php/tests/Rector/Property/CompleteVarDocTypePropertyRector/Source/EventDispatcher.php", + "packages/TypeDeclaration/tests/Rector/Property/CompleteVarDocTypePropertyRector/Source/EventDispatcher.php", "tests/Rector/Namespace_/PseudoNamespaceToNamespaceRector/Source/ChangeMeAnotherNamespace.php", "packages/TypeDeclaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/Source/MyBar.php", "tests/Rector/Class_/RenameClassRector/Source/Twig_Extension_Sandbox.php", diff --git a/config/services.yaml b/config/services.yaml index d47c1ebe7d48..ece1936cf098 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -5,7 +5,7 @@ services: Rector\: resource: '../src' - exclude: '../src/{Node/Attribute.php,Rector/**/*Rector.php,Reporting/FileDiff.php,Testing/PHPUnit,RectorDefinition,PhpParser/Node/*Info.php,Exception/*,DependencyInjection/CompilerPass/*,DependencyInjection/Loader/*,Application/Error.php,HttpKernel/RectorKernel.php}' + exclude: '../src/{Node/Attribute.php,Rector/**/*Rector.php,Reporting/FileDiff.php,Testing/PHPUnit,RectorDefinition,PhpParser/Node/*Info.php,Exception/*,DependencyInjection/CompilerPass/*,DependencyInjection/Loader/*,Application/Error.php,HttpKernel/RectorKernel.php,ValueObject/*}' # extra services Rector\Symfony\Rector\Form\Helper\FormTypeStringToTypeProvider: ~ diff --git a/config/set/celebrity/celebrity.yaml b/config/set/celebrity/celebrity.yaml index b0a1c8b6b172..f75ac49fcdaa 100644 --- a/config/set/celebrity/celebrity.yaml +++ b/config/set/celebrity/celebrity.yaml @@ -10,7 +10,8 @@ services: Rector\Celebrity\Rector\FuncCall\SetTypeToCastRector: ~ # class { var $value; } → class { public $value; } - Rector\Php\Rector\Property\VarToPublicPropertyRector: ~ + Rector\Php52\Rector\Property\VarToPublicPropertyRector: ~pu + # false or true → false || true # false and true → false && true diff --git a/config/set/code-quality/code-quality.yaml b/config/set/code-quality/code-quality.yaml index b72714aad6d9..7646201a2bda 100644 --- a/config/set/code-quality/code-quality.yaml +++ b/config/set/code-quality/code-quality.yaml @@ -15,7 +15,7 @@ services: Rector\CodeQuality\Rector\Return_\SimplifyUselessVariableRector: ~ Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector: ~ - Rector\Php\Rector\FuncCall\RemoveExtraParametersRector: ~ + Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector: ~ Rector\CodeQuality\Rector\BinaryOp\SimplifyDeMorganBinaryRector: ~ Rector\CodeQuality\Rector\Ternary\SimplifyTautologyTernaryRector: ~ Rector\CodeQuality\Rector\Foreach_\SimplifyForeachToArrayFilterRector: ~ diff --git a/config/set/coding-style/coding-style.yaml b/config/set/coding-style/coding-style.yaml index 0c719bdc1bd1..8ebd7b65162a 100644 --- a/config/set/coding-style/coding-style.yaml +++ b/config/set/coding-style/coding-style.yaml @@ -15,7 +15,7 @@ services: Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector: ~ # 'ClassName' → ClassName::class - Rector\Php\Rector\String_\StringClassNameToClassConstantRector: ~ + Rector\Php55\Rector\String_\StringClassNameToClassConstantRector: ~ Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector: ~ Rector\CodingStyle\Rector\Include_\FollowRequireByDirRector: ~ Rector\CodingStyle\Rector\Catch_\CatchExceptionNameMatchingTypeRector: ~ diff --git a/config/set/php/php52.yaml b/config/set/php/php52.yaml index 9372b6b2b2af..21c8c709243d 100644 --- a/config/set/php/php52.yaml +++ b/config/set/php/php52.yaml @@ -1,3 +1,3 @@ services: - Rector\Php\Rector\Property\VarToPublicPropertyRector: ~ - Rector\Php\Rector\Switch_\ContinueToBreakInSwitchRector: ~ + Rector\Php52\Rector\Property\VarToPublicPropertyRector: ~ + Rector\Php52\Rector\Switch_\ContinueToBreakInSwitchRector: ~ diff --git a/config/set/php/php53.yaml b/config/set/php/php53.yaml index 8383dffda1ae..a57e8942902f 100644 --- a/config/set/php/php53.yaml +++ b/config/set/php/php53.yaml @@ -1,2 +1,2 @@ services: - Rector\CodeQuality\Rector\Ternary\TernaryToElvisRector: ~ + Rector\Php53\Rector\Ternary\TernaryToElvisRector: ~ diff --git a/config/set/php/php54.yaml b/config/set/php/php54.yaml index 46e39fbd925d..bd34a5875523 100644 --- a/config/set/php/php54.yaml +++ b/config/set/php/php54.yaml @@ -1,4 +1,5 @@ services: Rector\Rector\Function_\RenameFunctionRector: mysqli_param_count: 'mysqli_stmt_param_count' - Rector\Php\Rector\FuncCall\RemoveReferenceFromCallRector: ~ + + Rector\Php54\Rector\FuncCall\RemoveReferenceFromCallRector: ~ diff --git a/config/set/php/php55.yaml b/config/set/php/php55.yaml index 7f5e79d18220..fd57921cf8d3 100644 --- a/config/set/php/php55.yaml +++ b/config/set/php/php55.yaml @@ -1,2 +1,2 @@ services: - Rector\Php\Rector\String_\StringClassNameToClassConstantRector: ~ + Rector\Php55\Rector\String_\StringClassNameToClassConstantRector: ~ diff --git a/config/set/php/php56.yaml b/config/set/php/php56.yaml index b1cc88198921..614e8beb42be 100644 --- a/config/set/php/php56.yaml +++ b/config/set/php/php56.yaml @@ -1,5 +1,5 @@ services: - Rector\Php\Rector\FuncCall\PowToExpRector: ~ + Rector\Php56\Rector\FuncCall\PowToExpRector: ~ Rector\Rector\Function_\RenameFunctionRector: mcrypt_generic_end: 'mcrypt_generic_deinit' @@ -39,4 +39,4 @@ services: ocistatementtype: 'oci_statement_type' # inspired by level in psalm - https://github.com/vimeo/psalm/blob/82e0bcafac723fdf5007a31a7ae74af1736c9f6f/tests/FileManipulationTest.php#L1063 - Rector\Php\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector: ~ + Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector: ~ diff --git a/config/set/php/php70.yaml b/config/set/php/php70.yaml index 7de8949bdcf0..64871442688f 100644 --- a/config/set/php/php70.yaml +++ b/config/set/php/php70.yaml @@ -2,24 +2,24 @@ imports: - { resource: "../database-migration/mysql-to-mysqli.yaml" } services: - Rector\Php\Rector\FunctionLike\Php4ConstructorRector: ~ - Rector\Php\Rector\Ternary\TernaryToNullCoalescingRector: ~ - Rector\Php\Rector\FuncCall\RandomFunctionRector: ~ - Rector\Php\Rector\FunctionLike\ExceptionHandlerTypehintRector: ~ - Rector\Php\Rector\FuncCall\MultiDirnameRector: ~ - Rector\Php\Rector\List_\ListSplitStringRector: ~ - Rector\Php\Rector\List_\EmptyListRector: ~ + Rector\Php70\Rector\FunctionLike\Php4ConstructorRector: ~ + Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector: ~ + Rector\Php70\Rector\FuncCall\RandomFunctionRector: ~ + Rector\Php70\Rector\FunctionLike\ExceptionHandlerTypehintRector: ~ + Rector\Php70\Rector\FuncCall\MultiDirnameRector: ~ + Rector\Php70\Rector\List_\ListSplitStringRector: ~ + Rector\Php70\Rector\List_\EmptyListRector: ~ # be careful, run this just once, since it can keep swapping order back and forth - Rector\Php\Rector\List_\ListSwapArrayOrderRector: ~ + Rector\Php70\Rector\List_\ListSwapArrayOrderRector: ~ - Rector\Php\Rector\FuncCall\CallUserMethodRector : ~ - Rector\Php\Rector\FuncCall\EregToPregMatchRector: ~ - Rector\Php\Rector\Switch_\ReduceMultipleDefaultSwitchRector: ~ - Rector\Php\Rector\Ternary\TernaryToSpaceshipRector: ~ - Rector\Php\Rector\If_\IfToSpaceshipRector: ~ - Rector\Php\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector: ~ - Rector\Php\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector: ~ + Rector\Php70\Rector\FuncCall\CallUserMethodRector : ~ + Rector\Php70\Rector\FuncCall\EregToPregMatchRector: ~ + Rector\Php70\Rector\Switch_\ReduceMultipleDefaultSwitchRector: ~ + Rector\Php70\Rector\Ternary\TernaryToSpaceshipRector: ~ + Rector\Php70\Rector\If_\IfToSpaceshipRector: ~ + Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector: ~ + Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector: ~ - Rector\Php\Rector\Break_\BreakNotInLoopOrSwitchToReturnRector: ~ - Rector\Php\Rector\FuncCall\RenameMktimeWithoutArgsToTimeRector: ~ + Rector\Php70\Rector\Break_\BreakNotInLoopOrSwitchToReturnRector: ~ + Rector\Php70\Rector\FuncCall\RenameMktimeWithoutArgsToTimeRector: ~ diff --git a/config/set/php/php71.yaml b/config/set/php/php71.yaml index 1e23a2282238..811d4cb7a341 100644 --- a/config/set/php/php71.yaml +++ b/config/set/php/php71.yaml @@ -1,10 +1,12 @@ services: - Rector\Php\Rector\BinaryOp\IsIterableRector: ~ + Rector\Php71\Rector\BinaryOp\IsIterableRector: ~ + Rector\Php\Rector\Name\ReservedObjectRector: - Object: 'BaseObject' + $reservedKeywordsToReplacements: + Object: 'BaseObject' - Rector\Php\Rector\TryCatch\MultiExceptionCatchRector: ~ - Rector\Php\Rector\Assign\AssignArrayToStringRector: ~ - Rector\Php\Rector\FuncCall\CountOnNullRector: ~ - Rector\Php\Rector\FuncCall\RemoveExtraParametersRector: ~ - Rector\Php\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector: ~ + Rector\Php71\Rector\TryCatch\MultiExceptionCatchRector: ~ + Rector\Php71\Rector\Assign\AssignArrayToStringRector: ~ + Rector\Php71\Rector\FuncCall\CountOnNullRector: ~ + Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector: ~ + Rector\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector: ~ diff --git a/config/set/php/php72.yaml b/config/set/php/php72.yaml index 19d640427867..4994686c3c5d 100644 --- a/config/set/php/php72.yaml +++ b/config/set/php/php72.yaml @@ -3,10 +3,10 @@ parameters: enable_object_type: true services: - Rector\Php\Rector\Each\WhileEachToForeachRector: ~ - Rector\Php\Rector\Each\ListEachRector: ~ - Rector\Php\Rector\Unset_\UnsetCastRector: ~ - Rector\Php\Rector\ConstFetch\BarewordStringRector: ~ + Rector\Php72\Rector\Each\WhileEachToForeachRector: ~ + Rector\Php72\Rector\Each\ListEachRector: ~ + Rector\Php72\Rector\Unset_\UnsetCastRector: ~ + Rector\Php72\Rector\ConstFetch\BarewordStringRector: ~ Rector\Rector\Function_\RenameFunctionRector: jpeg2wbmp: 'imagecreatefromjpeg' # and imagewbmp @@ -15,9 +15,9 @@ services: gmp_random: 'gmp_random_bits' # or gmp_random_range read_exif_data: 'exif_read_data' - Rector\Php\Rector\FuncCall\GetClassOnNullRector: ~ - Rector\Php\Rector\FuncCall\IsObjectOnIncompleteClassRector: ~ - Rector\Php\Rector\FuncCall\ParseStrWithResultArgumentRector: ~ - Rector\Php\Rector\FuncCall\StringsAssertNakedRector: ~ - Rector\Php\Rector\FuncCall\CreateFunctionToAnonymousFunctionRector: ~ - Rector\Php\Rector\FuncCall\StringifyDefineRector: ~ + Rector\Php72\Rector\FuncCall\GetClassOnNullRector: ~ + Rector\Php72\Rector\FuncCall\IsObjectOnIncompleteClassRector: ~ + Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector: ~ + Rector\Php72\Rector\FuncCall\StringsAssertNakedRector: ~ + Rector\Php72\Rector\FuncCall\CreateFunctionToAnonymousFunctionRector: ~ + Rector\Php72\Rector\FuncCall\StringifyDefineRector: ~ diff --git a/config/set/php/php73.yaml b/config/set/php/php73.yaml index 25783f28f3e4..b72207b5bfaa 100644 --- a/config/set/php/php73.yaml +++ b/config/set/php/php73.yaml @@ -1,9 +1,9 @@ services: - Rector\Php\Rector\BinaryOp\IsCountableRector: ~ - Rector\Php\Rector\FuncCall\ArrayKeyFirstLastRector: ~ - Rector\Php\Rector\FuncCall\SensitiveDefineRector: ~ - Rector\Php\Rector\ConstFetch\SensitiveConstantNameRector: ~ - Rector\Php\Rector\String_\SensitiveHereNowDocRector: ~ + Rector\Php73\Rector\BinaryOp\IsCountableRector: ~ + Rector\Php73\Rector\FuncCall\ArrayKeyFirstLastRector: ~ + Rector\Php73\Rector\FuncCall\SensitiveDefineRector: ~ + Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector: ~ + Rector\Php73\Rector\String_\SensitiveHereNowDocRector: ~ # https://wiki.php.net/rfc/deprecations_php_7_3 Rector\Rector\Function_\RenameFunctionRector: @@ -22,7 +22,7 @@ services: mbereg_search_getregs: 'mb_ereg_search_getregs' mbereg_search_getpos: 'mb_ereg_search_getpos' - Rector\Php\Rector\FuncCall\StringifyStrNeedlesRector: ~ - Rector\Php\Rector\FuncCall\JsonThrowOnErrorRector: ~ - Rector\Php\Rector\FuncCall\RegexDashEscapeRector: ~ - Rector\Php\Rector\FuncCall\RemoveMissingCompactVariableRector: ~ + Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector: ~ + Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector: ~ + Rector\Php73\Rector\FuncCall\RegexDashEscapeRector: ~ + Rector\Php73\Rector\FuncCall\RemoveMissingCompactVariableRector: ~ diff --git a/config/set/php/php74.yaml b/config/set/php/php74.yaml index cb39f9b98eed..d97fa7548ff4 100644 --- a/config/set/php/php74.yaml +++ b/config/set/php/php74.yaml @@ -1,5 +1,5 @@ services: - Rector\Php\Rector\Property\TypedPropertyRector: ~ + Rector\Php74\Rector\Property\TypedPropertyRector: ~ Rector\Rector\Function_\RenameFunctionRector: # https://wiki.php.net/rfc/deprecations_php_7_4#the_real_type @@ -7,15 +7,15 @@ services: # https://wiki.php.net/rfc/deprecations_php_7_4#apache_request_headers_function apache_request_headers: 'getallheaders' hebrevc: ['nl2br', 'hebrev'] - Rector\Php\Rector\FuncCall\ArrayKeyExistsOnPropertyRector: ~ - Rector\Php\Rector\FuncCall\FilterVarToAddSlashesRector: ~ - Rector\Php\Rector\StaticCall\ExportToReflectionFunctionRector: ~ - Rector\Php\Rector\MagicConstClass\ClassConstantToSelfClassRector: ~ - Rector\Php\Rector\FuncCall\GetCalledClassToStaticClassRector: ~ - Rector\Php\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector: ~ - Rector\Php\Rector\Double\RealToFloatTypeCastRector: ~ - Rector\Php\Rector\Assign\NullCoalescingOperatorRector: ~ - Rector\Php\Rector\Function_\ReservedFnFunctionRector: ~ - Rector\Php\Rector\Closure\ClosureToArrowFunctionRector: ~ - Rector\Php\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector: ~ - Rector\Php\Rector\LNumber\AddLiteralSeparatorToNumberRector: ~ + Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector: ~ + Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector: ~ + Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector: ~ + Rector\Php74\Rector\MagicConstClass\ClassConstantToSelfClassRector: ~ + Rector\Php74\Rector\FuncCall\GetCalledClassToStaticClassRector: ~ + Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector: ~ + Rector\Php74\Rector\Double\RealToFloatTypeCastRector: ~ + Rector\Php74\Rector\Assign\NullCoalescingOperatorRector: ~ + Rector\Php74\Rector\Function_\ReservedFnFunctionRector: ~ + Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector: ~ + Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector: ~ + Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector: ~ diff --git a/ecs.yaml b/ecs.yaml index 153f5b8e34dd..4c5b70105b86 100644 --- a/ecs.yaml +++ b/ecs.yaml @@ -76,7 +76,7 @@ parameters: Symplify\CodingStandard\Fixer\Order\PrivateMethodOrderByUseFixer: ~ PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer: - - 'packages/Php/src/Rector/Double/RealToFloatTypeCastRector.php' + - 'packages/Php74/src/Rector/Double/RealToFloatTypeCastRector.php' Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenReferenceSniff: ~ @@ -119,7 +119,7 @@ parameters: - 'packages/TypeDeclaration/src/TypeInferer/ReturnTypeInferer/ReturnedNodesReturnTypeInferer.php' - 'packages/NodeTypeResolver/src/NodeTypeResolver.php' - 'packages/NodeTypeResolver/src/PerNodeTypeResolver/VariableTypeResolver.php' - - 'packages/Php/src/Rector/FuncCall/RemoveExtraParametersRector.php' + - 'packages/Php71/src/Rector/FuncCall/RemoveExtraParametersRector.php' - 'packages/SOLID/src/Analyzer/ClassConstantFetchAnalyzer.php' # tough logic - 'packages/PHPUnit/src/Rector/Class_/ArrayArgumentInTestToDataProviderRector.php' @@ -153,7 +153,7 @@ parameters: - 'packages/Php/src/EregToPcreTransformer.php' # dev - 'packages/TypeDeclaration/src/Rector/FunctionLike/*TypeDeclarationRector.php' - - 'packages/Php/src/Rector/If_/IfToSpaceshipRector.php' + - 'packages/Php70/src/Rector/If_/IfToSpaceshipRector.php' Symplify\CodingStandard\Sniffs\ControlStructure\SprintfOverContactSniff: # respects inherited pattern for better comparing @@ -173,7 +173,7 @@ parameters: Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff.Found: # notes - - 'packages/Php/src/Rector/Each/ListEachRector.php' + - 'packages/Php72/src/Rector/Each/ListEachRector.php' - 'packages/DeadCode/src/Rector/ClassMethod/RemoveOverriddenValuesRector.php' - 'packages/PhpSpecToPHPUnit/src/Rector/MethodCall/PhpSpecPromisesToPHPUnitAssertRector.php' diff --git a/packages/Autodiscovery/src/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector.php b/packages/Autodiscovery/src/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector.php index f4857a15057f..44971e520312 100644 --- a/packages/Autodiscovery/src/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector.php +++ b/packages/Autodiscovery/src/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector.php @@ -97,7 +97,7 @@ private function processGroupNamesBySuffix( continue; } - $this->moveFile($smartFileInfo, $nodes, $groupName); + $this->moveFileToGroupName($smartFileInfo, $nodes, $groupName); return; } } @@ -105,7 +105,7 @@ private function processGroupNamesBySuffix( /** * @param Node[] $nodes */ - private function moveFile(SmartFileInfo $smartFileInfo, array $nodes, string $desiredGroupName): void + private function moveFileToGroupName(SmartFileInfo $smartFileInfo, array $nodes, string $desiredGroupName): void { $nodesWithFileDestination = $this->fileMover->createMovedNodesAndFilePath( $smartFileInfo, diff --git a/packages/CodeQuality/src/Rector/If_/SimplifyIfIssetToNullCoalescingRector.php b/packages/CodeQuality/src/Rector/If_/SimplifyIfIssetToNullCoalescingRector.php index 309845ee5b45..41bf9d572f22 100644 --- a/packages/CodeQuality/src/Rector/If_/SimplifyIfIssetToNullCoalescingRector.php +++ b/packages/CodeQuality/src/Rector/If_/SimplifyIfIssetToNullCoalescingRector.php @@ -76,7 +76,6 @@ public function refactor(Node $node): ?Node $valueNode = $issetNode->vars[0]; // various scenarios - /** @var Assign $firstAssign */ $firstAssign = $node->stmts[0]->expr; /** @var Assign $secondAssign */ diff --git a/packages/CodeQuality/tests/Rector/BooleanAnd/SimplifyEmptyArrayCheckRector/Fixture/fixture.php.inc b/packages/CodeQuality/tests/Rector/BooleanAnd/SimplifyEmptyArrayCheckRector/Fixture/fixture.php.inc index abd8fe16da90..d70c9a162f1c 100644 --- a/packages/CodeQuality/tests/Rector/BooleanAnd/SimplifyEmptyArrayCheckRector/Fixture/fixture.php.inc +++ b/packages/CodeQuality/tests/Rector/BooleanAnd/SimplifyEmptyArrayCheckRector/Fixture/fixture.php.inc @@ -1,5 +1,7 @@ 0; $invalid2 = isset($this->events[$event]) && !empty($this->events[$event]); - $completelyInvalid = !$value instanceof Foo && !$value instanceof Bar; + $completelyInvalid = !$value instanceof \Foo && !$value instanceof \Bar; if (empty($this->orders) && empty($this->unionOrders)) { - throw new RuntimeException('You must specify an orderBy clause when using this function.'); + throw new \RuntimeException('You must specify an orderBy clause when using this function.'); } echo is_array($objects) && is_array($objects); @@ -18,15 +20,17 @@ function simplifyEmptyCheck() ----- 0; $invalid2 = isset($this->events[$event]) && !empty($this->events[$event]); - $completelyInvalid = !$value instanceof Foo && !$value instanceof Bar; + $completelyInvalid = !$value instanceof \Foo && !$value instanceof \Bar; if (empty($this->orders) && empty($this->unionOrders)) { - throw new RuntimeException('You must specify an orderBy clause when using this function.'); + throw new \RuntimeException('You must specify an orderBy clause when using this function.'); } echo is_array($objects) && is_array($objects); diff --git a/packages/DeadCode/src/Rector/ClassMethod/RemoveOverriddenValuesRector.php b/packages/DeadCode/src/Rector/ClassMethod/RemoveOverriddenValuesRector.php index 3dac77194150..35905da7f4f5 100644 --- a/packages/DeadCode/src/Rector/ClassMethod/RemoveOverriddenValuesRector.php +++ b/packages/DeadCode/src/Rector/ClassMethod/RemoveOverriddenValuesRector.php @@ -191,7 +191,6 @@ private function collectNodesByTypeAndPosition( // not in different scope, than previous one - e.g. if/while/else... // get nesting level to $classMethodNode - /** @var Assign $assignNode */ $assignNode = $assignedVariable->getAttribute(AttributeKey::PARENT_NODE); $nestingHash = $this->flowOfControlLocator->resolveNestingHashFromFunctionLike($functionLike, $assignNode); @@ -286,7 +285,6 @@ private function shouldRemoveAssignNode( // check previous node doesn't contain the node on the right, e.g. // $someNode = 1; // $someNode = $someNode ?: 1; - /** @var Assign $assignNode */ $assignNode = $nodeByTypeAndPosition->getParentNode(); diff --git a/packages/FileSystemRector/src/Rector/AbstractFileSystemRector.php b/packages/FileSystemRector/src/Rector/AbstractFileSystemRector.php index cb5d1fe76074..8964d393a942 100644 --- a/packages/FileSystemRector/src/Rector/AbstractFileSystemRector.php +++ b/packages/FileSystemRector/src/Rector/AbstractFileSystemRector.php @@ -65,7 +65,7 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface /** * @required */ - public function setAbstractFileSystemRectorDependencies( + public function autowireAbstractFileSystemRector( Parser $parser, ParserFactory $parserFactory, Lexer $lexer, @@ -100,6 +100,17 @@ protected function parseFileInfoToNodes(SmartFileInfo $smartFileInfo): array ); } + /** + * @return Node[] + */ + protected function parseFileInfoToNodesWithoutScope(SmartFileInfo $smartFileInfo): array + { + $oldStmts = $this->parser->parseFile($smartFileInfo->getRealPath()); + $this->oldStmts = $oldStmts; + + return $oldStmts; + } + /** * @param Node[] $nodes */ @@ -164,6 +175,11 @@ protected function printNodesWithFileDestination( ); } + protected function moveFile(SmartFileInfo $oldFileInfo, string $newFileLocation, ?string $fileContent = null): void + { + $this->removedAndAddedFilesCollector->addMovedFile($oldFileInfo, $newFileLocation, $fileContent); + } + protected function removeFile(SmartFileInfo $smartFileInfo): void { $this->removedAndAddedFilesCollector->removeFile($smartFileInfo); diff --git a/packages/NodeTypeResolver/src/NodeScopeAndMetadataDecorator.php b/packages/NodeTypeResolver/src/NodeScopeAndMetadataDecorator.php index d880ce6366bf..e53bf5d58c20 100644 --- a/packages/NodeTypeResolver/src/NodeScopeAndMetadataDecorator.php +++ b/packages/NodeTypeResolver/src/NodeScopeAndMetadataDecorator.php @@ -6,6 +6,7 @@ use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\CloningVisitor; use PhpParser\NodeVisitor\NameResolver; +use Rector\Configuration\Configuration; use Rector\NodeTypeResolver\NodeVisitor\ClassAndMethodNodeVisitor; use Rector\NodeTypeResolver\NodeVisitor\ExpressionNodeVisitor; use Rector\NodeTypeResolver\NodeVisitor\FileInfoNodeVisitor; @@ -56,6 +57,11 @@ final class NodeScopeAndMetadataDecorator */ private $nodeCollectorNodeVisitor; + /** + * @var Configuration + */ + private $configuration; + public function __construct( NodeScopeResolver $nodeScopeResolver, ParentAndNextNodeVisitor $parentAndNextNodeVisitor, @@ -64,7 +70,8 @@ public function __construct( NamespaceNodeVisitor $namespaceNodeVisitor, ExpressionNodeVisitor $expressionNodeVisitor, FileInfoNodeVisitor $fileInfoNodeVisitor, - NodeCollectorNodeVisitor $nodeCollectorNodeVisitor + NodeCollectorNodeVisitor $nodeCollectorNodeVisitor, + Configuration $configuration ) { $this->nodeScopeResolver = $nodeScopeResolver; $this->parentAndNextNodeVisitor = $parentAndNextNodeVisitor; @@ -74,6 +81,7 @@ public function __construct( $this->expressionNodeVisitor = $expressionNodeVisitor; $this->fileInfoNodeVisitor = $fileInfoNodeVisitor; $this->nodeCollectorNodeVisitor = $nodeCollectorNodeVisitor; + $this->configuration = $configuration; } /** @@ -89,7 +97,10 @@ public function decorateNodesFromFile(array $nodes, string $filePath): array ])); $nodes = $nodeTraverser->traverse($nodes); - $nodes = $this->nodeScopeResolver->processNodes($nodes, $filePath); + // node scoping is needed only for Scope + if ($this->configuration->areAnyPhpRectorsLoaded()) { + $nodes = $this->nodeScopeResolver->processNodes($nodes, $filePath); + } $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor(new NameResolver(null, [ diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php index 0e3a7b7bf852..3fc62f199a92 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php @@ -8,6 +8,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; use PHPStan\Type\Type; +use Rector\Exception\ShouldNotHappenException; use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory; @@ -44,8 +45,11 @@ public function getNodeClasses(): array */ public function resolve(Node $node): Type { - /** @var Scope $nodeScope */ + /** @var Scope|null $nodeScope */ $nodeScope = $node->getAttribute(AttributeKey::SCOPE); + if ($nodeScope === null) { + throw new ShouldNotHappenException(); + } /** @var ClassReflection $classReflection */ $classReflection = $nodeScope->getClassReflection(); diff --git a/packages/NodeTypeResolver/src/StaticTypeMapper.php b/packages/NodeTypeResolver/src/StaticTypeMapper.php index de7364aa6a81..dc2c32c30cf2 100644 --- a/packages/NodeTypeResolver/src/StaticTypeMapper.php +++ b/packages/NodeTypeResolver/src/StaticTypeMapper.php @@ -689,7 +689,6 @@ private function matchTypeForUnionedObjectTypes(UnionType $unionType): ?Node } // @todo the type should be compatible with all other types, check with is_a()? - /** @var TypeWithClassName $firstObjectType */ $firstObjectType = $unionType->getTypes()[0]; diff --git a/packages/PSR4/src/FileRelocationResolver.php b/packages/PSR4/src/FileRelocationResolver.php index 9d74f3c426e9..812df321ea16 100644 --- a/packages/PSR4/src/FileRelocationResolver.php +++ b/packages/PSR4/src/FileRelocationResolver.php @@ -2,15 +2,19 @@ namespace Rector\PSR4; +use Nette\Utils\Strings; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Namespace_; +use Rector\ValueObject\RenamedNamespaceValueObject; use Symplify\PackageBuilder\FileSystem\SmartFileInfo; -/** - * Will be used later - */ final class FileRelocationResolver { + /** + * @var string + */ + private const NAMESPACE_SEPARATOR = '\\'; + /** * @param string[] $groupNames */ @@ -33,7 +37,34 @@ public function resolveNewNamespaceName(Namespace_ $namespace, string $suffixNam $name = $namespace->name; $currentNamespaceParts = $name->parts; - return $this->resolveNearestRootWithCategory($currentNamespaceParts, $suffixName, '\\', $groupNames); + return $this->resolveNearestRootWithCategory( + $currentNamespaceParts, + $suffixName, + self::NAMESPACE_SEPARATOR, + $groupNames + ); + } + + public function resolveNewFileLocationFromRenamedNamespace( + SmartFileInfo $smartFileInfo, + RenamedNamespaceValueObject $renamedNamespaceValueObject + ): string { + $beforeToAfterPart = $this->resolveBeforeToAfterPartBetweenClassNames( + $renamedNamespaceValueObject->getOldNamespace(), + $renamedNamespaceValueObject->getNewNamespace() + ); + + return $this->replaceRalativeFilePathsWithBeforeAfter($smartFileInfo, $beforeToAfterPart); + } + + public function resolveNewFileLocationFromOldClassToNewClass( + SmartFileInfo $smartFileInfo, + string $oldClass, + string $newClass + ): string { + $beforeToAfterPart = $this->resolveBeforeToAfterPartBetweenClassNames($oldClass, $newClass); + + return $this->replaceRalativeFilePathsWithBeforeAfter($smartFileInfo, $beforeToAfterPart); } /** @@ -92,4 +123,56 @@ private function resolveNearestRootWithCategory( return implode($separator, $rootNameParts); } + + /** + * @return string[] + */ + private function resolveBeforeToAfterPartBetweenClassNames(string $oldClass, string $newClass): array + { + $oldClassNameParts = explode(self::NAMESPACE_SEPARATOR, $oldClass); + $newClassNameParts = explode(self::NAMESPACE_SEPARATOR, $newClass); + + $beforeToAfterParts = []; + foreach ($oldClassNameParts as $key => $oldClassNamePart) { + if (! isset($newClassNameParts[$key])) { + continue; + } + + $newClassNamePart = $newClassNameParts[$key]; + if ($oldClassNamePart === $newClassNamePart) { + continue; + } + + $beforeToAfterParts[$oldClassNamePart] = $newClassNamePart; + } + + return $beforeToAfterParts; + } + + /** + * @param string[] $beforeToAfterPart + */ + private function replaceRalativeFilePathsWithBeforeAfter( + SmartFileInfo $oldSmartFileInfo, + array $beforeToAfterPart + ): string { + // A. first "dir has changed" dummy detection + $relativeFilePathParts = Strings::split( + $oldSmartFileInfo->getRelativeFilePath(), + '#' . DIRECTORY_SEPARATOR . '#' + ); + + foreach ($relativeFilePathParts as $key => $relativeFilePathPart) { + if (! isset($beforeToAfterPart[$relativeFilePathPart])) { + continue; + } + + $relativeFilePathParts[$key] = $beforeToAfterPart[$relativeFilePathPart]; + + // clear from further use + unset($beforeToAfterPart[$relativeFilePathPart]); + } + + return implode(DIRECTORY_SEPARATOR, $relativeFilePathParts); + } } diff --git a/packages/PSR4/tests/FileRelocationResolverTest.php b/packages/PSR4/tests/FileRelocationResolverTest.php new file mode 100644 index 000000000000..ac7b3d6e48a2 --- /dev/null +++ b/packages/PSR4/tests/FileRelocationResolverTest.php @@ -0,0 +1,54 @@ +bootKernel(RectorKernel::class); + + $this->fileRelocationResolver = self::$container->get(FileRelocationResolver::class); + } + + /** + * @dataProvider provideDataForTest() + */ + public function test(string $file, string $oldClass, string $newClass, string $expectedNewFileLocation): void + { + $smartFileInfo = new SmartFileInfo($file); + + $newFileLocation = $this->fileRelocationResolver->resolveNewFileLocationFromOldClassToNewClass( + $smartFileInfo, + $oldClass, + $newClass + ); + + $this->assertSame($expectedNewFileLocation, $newFileLocation); + } + + /** + * @return string[] + */ + public function provideDataForTest(): Iterator + { + yield [ + __DIR__ . '/Source/SomeFile.php', + SomeFile::class, + 'Rector\PSR10\Tests\Source\SomeFile', + 'packages/PSR10/tests/Source/SomeFile.php', + ]; + } +} diff --git a/packages/PSR4/tests/Source/SomeFile.php b/packages/PSR4/tests/Source/SomeFile.php new file mode 100644 index 000000000000..2db96953c69d --- /dev/null +++ b/packages/PSR4/tests/Source/SomeFile.php @@ -0,0 +1,8 @@ + 'length', - 'mysql_field_name' => 'name', - 'mysql_field_table' => 'table', - ]; - - public function getDefinition(): RectorDefinition - { - return new RectorDefinition( - 'Converts more complex mysql functions to mysqli', - [ - new CodeSample( - <<<'PHP' -$data = mysql_db_name($result, $row); -PHP - , - <<<'PHP' -mysqli_data_seek($result, $row); -$fetch = mysql_fetch_row($result); -$data = $fetch[0]; -PHP - ), - ] - ); - } - - /** - * @return string[] - */ - public function getNodeTypes(): array - { - return [Assign::class]; - } - - /** - * @param Assign $node - */ - public function refactor(Node $node): ?Node - { - if (! $node->expr instanceof FuncCall) { - return null; - } - - /** @var FuncCall $funcCallNode */ - $funcCallNode = $node->expr; - - if ($this->isName($funcCallNode, 'mysql_tablename')) { - return $this->processMysqlTableName($node, $funcCallNode); - } - - if ($this->isName($funcCallNode, 'mysql_db_name')) { - return $this->processMysqlDbName($node, $funcCallNode); - } - - if ($this->isName($funcCallNode, 'mysql_db_query')) { - return $this->processMysqliSelectDb($node, $funcCallNode); - } - - if ($this->isName($funcCallNode, 'mysql_fetch_field')) { - return $this->processMysqlFetchField($node, $funcCallNode); - } - - return $this->processFieldToFieldDirect($node, $funcCallNode); - } - - private function processMysqlTableName(Assign $assign, FuncCall $funcCall): FuncCall - { - $funcCall->name = new Name('mysqli_data_seek'); - - $newFuncCall = new FuncCall(new Name('mysql_fetch_array'), [$funcCall->args[0]]); - $newAssignNode = new Assign($assign->var, new ArrayDimFetch($newFuncCall, new LNumber(0))); - - $this->addNodeAfterNode($newAssignNode, $assign); - - return $funcCall; - } - - private function processMysqlDbName(Assign $assign, FuncCall $funcCall): FuncCall - { - $funcCall->name = new Name('mysqli_data_seek'); - - $mysqlFetchRowFuncCall = new FuncCall(new Name('mysql_fetch_row'), [$funcCall->args[0]]); - $fetchVariable = new Variable('fetch'); - $newAssignNode = new Assign($fetchVariable, $mysqlFetchRowFuncCall); - $this->addNodeAfterNode($newAssignNode, $assign); - - $newAssignNode = new Assign($assign->var, new ArrayDimFetch($fetchVariable, new LNumber(0))); - $this->addNodeAfterNode($newAssignNode, $assign); - - return $funcCall; - } - - private function processMysqliSelectDb(Assign $assign, FuncCall $funcCall): FuncCall - { - $funcCall->name = new Name('mysqli_select_db'); - - $newAssignNode = new Assign($assign->var, new FuncCall(new Name('mysqli_query'), [$funcCall->args[1]])); - $this->addNodeAfterNode($newAssignNode, $assign); - - unset($funcCall->args[1]); - - return $funcCall; - } - - private function processMysqlFetchField(Assign $assign, FuncCall $funcCall): Assign - { - $funcCall->name = new Name('mysqli_fetch_field'); - - if (! isset($funcCall->args[1])) { - return $assign; - } - - unset($funcCall->args[1]); - - // add for - $xVar = new Variable('x'); - $forNode = new For_([ - 'init' => [new Assign($xVar, new LNumber(0))], - 'cond' => [new Smaller($xVar, new LNumber(5))], - 'loop' => [new PostInc($xVar)], - 'stmts' => [new Expression($funcCall)], - ]); - - $previousExpression = $assign->getAttribute(AttributeKey::PREVIOUS_EXPRESSION); - if ($previousExpression === null) { - throw new ShouldNotHappenException(); - } - - $this->addNodeAfterNode($forNode, $previousExpression); - - return $assign; - } - - private function processFieldToFieldDirect(Assign $assign, FuncCall $funcCall): ?Assign - { - foreach ($this->fieldToFieldDirect as $funcName => $property) { - if ($this->isName($funcCall, $funcName)) { - $parentNode = $funcCall->getAttribute(AttributeKey::PARENT_NODE); - if ($parentNode instanceof PropertyFetch) { - continue; - } - - $funcCall->name = new Name('mysqli_fetch_field_direct'); - $assign->expr = new PropertyFetch($funcCall, $property); - - return $assign; - } - } - - return null; - } -} diff --git a/packages/Php/tests/EregToPcreTransformerTest.php b/packages/Php/tests/EregToPcreTransformerTest.php index 94b73d11510f..c5c2a48e8f99 100644 --- a/packages/Php/tests/EregToPcreTransformerTest.php +++ b/packages/Php/tests/EregToPcreTransformerTest.php @@ -19,7 +19,7 @@ protected function setUp(): void } /** - * @dataProvider provideDataDroping() + * @dataProvider provideDataDropping() * @dataProvider provideDataCaseSensitive() */ public function testCaseSensitive(string $ereg, string $expectedPcre): void @@ -47,7 +47,7 @@ public function provideDataCaseInsensitive(): Iterator yield ['hi', '#hi#mi']; } - public function provideDataDroping(): Iterator + public function provideDataDropping(): Iterator { yield ['mearie\.org', '#mearie\.org#m']; yield ['mearie[.,]org', '#mearie[\.,]org#m']; diff --git a/packages/Php/tests/Rector/Assign/AssignArrayToStringRector/Fixture/fixture9.php.inc b/packages/Php/tests/Rector/Assign/AssignArrayToStringRector/Fixture/fixture9.php.inc deleted file mode 100644 index e98b59864c62..000000000000 --- a/packages/Php/tests/Rector/Assign/AssignArrayToStringRector/Fixture/fixture9.php.inc +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/packages/Php/tests/Rector/FuncCall/CountOnNullRector/Fixture/array_countable_class.php.inc b/packages/Php/tests/Rector/FuncCall/CountOnNullRector/Fixture/array_countable_class.php.inc deleted file mode 100644 index ee909b3a147c..000000000000 --- a/packages/Php/tests/Rector/FuncCall/CountOnNullRector/Fixture/array_countable_class.php.inc +++ /dev/null @@ -1,12 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/better_func_get_all.php.inc b/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/better_func_get_all.php.inc deleted file mode 100644 index 0d58e7d97d09..000000000000 --- a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/better_func_get_all.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc b/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc deleted file mode 100644 index 6acf005ab132..000000000000 --- a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc +++ /dev/null @@ -1,8 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/class_property.php.inc b/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/class_property.php.inc deleted file mode 100644 index 34d469acd983..000000000000 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/class_property.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/nullable_property.php.inc b/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/nullable_property.php.inc deleted file mode 100644 index 0475d5197a04..000000000000 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/nullable_property.php.inc +++ /dev/null @@ -1,41 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/static_property.php.inc b/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/static_property.php.inc deleted file mode 100644 index 058dd4b2feea..000000000000 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/static_property.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Source/AnotherClass.php b/packages/Php/tests/Rector/Property/TypedPropertyRector/Source/AnotherClass.php deleted file mode 100644 index 8b21772bbe39..000000000000 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Source/AnotherClass.php +++ /dev/null @@ -1,8 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/pre_slash.php.inc b/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/pre_slash.php.inc deleted file mode 100644 index 288007794e3f..000000000000 --- a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/pre_slash.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_sensitive.php.inc b/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_sensitive.php.inc deleted file mode 100644 index c614765ae38b..000000000000 --- a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_sensitive.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - 'Exception']; - } -} - -?> ------ - \Exception::class]; - } -} - -?> diff --git a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_slashes.php.inc b/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_slashes.php.inc deleted file mode 100644 index a87dcdd57dfa..000000000000 --- a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_slashes.php.inc +++ /dev/null @@ -1,13 +0,0 @@ - +----- + diff --git a/packages/Php/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php b/packages/Php54/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php similarity index 81% rename from packages/Php/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php rename to packages/Php54/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php index 16e412d1833d..ab48a152aa8c 100644 --- a/packages/Php/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php +++ b/packages/Php54/tests/Rector/FuncCall/RemoveReferenceFromCallRector/RemoveReferenceFromCallRectorTest.php @@ -1,8 +1,8 @@ +----- + diff --git a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc b/packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc similarity index 56% rename from packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc rename to packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc index 39ce1d9e7e5f..b696be0850f2 100644 --- a/packages/Php/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc +++ b/packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Fixture/skip_error.php.inc @@ -1,6 +1,6 @@ 'Exception']; + } +} + +?> +----- + \Exception::class]; + } +} + +?> diff --git a/packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Source/AnotherClass.php b/packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Source/AnotherClass.php new file mode 100644 index 000000000000..8d835f4145c8 --- /dev/null +++ b/packages/Php55/tests/Rector/String_/StringClassNameToClassConstantRector/Source/AnotherClass.php @@ -0,0 +1,8 @@ + ---- +----- $b) ? 1 : 0); @@ -10,6 +12,8 @@ function order_func($a, $b) { ----- $b; diff --git a/packages/Php/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php b/packages/Php70/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php similarity index 81% rename from packages/Php/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php rename to packages/Php70/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php index f412bcbfbbb0..cfac2b5a87cd 100644 --- a/packages/Php/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php +++ b/packages/Php70/tests/Rector/Ternary/TernaryToSpaceshipRector/TernaryToSpaceshipRectorTest.php @@ -1,8 +1,8 @@ getStaticType($expr); - - if ($this->shouldSkipVariable($variableStaticType)) { + if ($this->shouldSkipVariable($expr)) { return true; } @@ -164,8 +161,9 @@ private function isEmptyStringNode(Node $node): bool return $node instanceof String_ && $node->value === ''; } - private function shouldSkipVariable(?Type $staticType): bool + private function shouldSkipVariable(Expr $expr): bool { + $staticType = $this->getStaticType($expr); if ($staticType instanceof ErrorType) { return false; } @@ -174,6 +172,7 @@ private function shouldSkipVariable(?Type $staticType): bool return ! ($staticType->isSuperTypeOf(new ArrayType(new MixedType(), new MixedType()))->yes() && $staticType->isSuperTypeOf(new ConstantStringType(''))->yes()); } + return ! $staticType instanceof StringType; } } diff --git a/packages/Php/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php b/packages/Php71/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php similarity index 91% rename from packages/Php/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php rename to packages/Php71/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php index 59b49eac6e0c..bc087d8ffb9e 100644 --- a/packages/Php/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php +++ b/packages/Php71/src/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php @@ -1,6 +1,6 @@ +----- + diff --git a/packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc b/packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc new file mode 100644 index 000000000000..cd372d5757d8 --- /dev/null +++ b/packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/external_scope.php.inc @@ -0,0 +1,10 @@ +theFunction(1); + $this->theFunction(1, 2); + $this->theFunction(1, 2, 3); + } + + private function theFunction($a, $b = 5) + { + } +} + +?> +----- +theFunction(1); + $this->theFunction(1, 2); + $this->theFunction(1, 2); + } + + private function theFunction($a, $b = 5) + { + } +} + +?> diff --git a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc b/packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc similarity index 85% rename from packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc rename to packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc index 6eb2e4628b72..d88b9386d869 100644 --- a/packages/Php/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc +++ b/packages/Php71/tests/Rector/FuncCall/RemoveExtraParametersRector/Fixture/methods.php.inc @@ -1,6 +1,6 @@ ------ - diff --git a/packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/fixture73.php.inc b/packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/fixture73.php.inc new file mode 100644 index 000000000000..8df717c4a455 --- /dev/null +++ b/packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/fixture73.php.inc @@ -0,0 +1,21 @@ + +----- + diff --git a/packages/Php/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc b/packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc similarity index 78% rename from packages/Php/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc rename to packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc index 072a2ed88a60..69a1cb809d85 100644 --- a/packages/Php/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc +++ b/packages/Php73/tests/Rector/BinaryOp/IsCountableRector/Fixture/polyfill_function.php.inc @@ -1,6 +1,6 @@ +----- + diff --git a/packages/Php/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc b/packages/Php74/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc similarity index 56% rename from packages/Php/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc rename to packages/Php74/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc index c4a658a2274c..48be34a6276f 100644 --- a/packages/Php/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc +++ b/packages/Php74/tests/Rector/FuncCall/GetCalledClassToStaticClassRector/Fixture/fixture.php.inc @@ -1,6 +1,6 @@ +----- + diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc b/packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc similarity index 91% rename from packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc rename to packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc index 4c507dd61404..c619b20460cb 100644 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc +++ b/packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/default_values.php.inc @@ -1,6 +1,6 @@ +----- + diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc b/packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc similarity index 80% rename from packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc rename to packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc index a34fc837b296..62086b44a835 100644 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc +++ b/packages/Php74/tests/Rector/Property/TypedPropertyRector/Fixture/property.php.inc @@ -1,6 +1,6 @@ +----- + diff --git a/packages/Php/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php b/packages/Php74/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php similarity index 91% rename from packages/Php/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php rename to packages/Php74/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php index d73a07b70f5b..46989ea99205 100644 --- a/packages/Php/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php +++ b/packages/Php74/tests/Rector/Property/TypedPropertyRector/TypedPropertyRectorTest.php @@ -1,8 +1,8 @@ fileRelocationResolver = $fileRelocationResolver; + $this->renamedClassesCollector = $renamedClassesCollector; + $this->oldClassToNewClass = $oldClassToNewClass; + } + + public function refactor(SmartFileInfo $smartFileInfo): void + { + $fileNodes = $this->parseFileInfoToNodes($smartFileInfo); + $fileContent = $smartFileInfo->getContents(); + + $class = $this->betterNodeFinder->findFirstClass($fileNodes); + if ($class === null) { + return; + } + + $className = $this->getName($class); + + /** @var string $oldClass */ + foreach ($this->oldClassToNewClass as $oldClass => $newClass) { + if ($className !== $oldClass) { + continue; + } + + $newFileLocation = $this->fileRelocationResolver->resolveNewFileLocationFromOldClassToNewClass( + $smartFileInfo, + $oldClass, + $newClass + ); + + // create helping rename class rector.yaml + class_alias autoload file + $this->renamedClassesCollector->addClassRename($oldClass, $newClass); + + $this->moveFile($smartFileInfo, $newFileLocation, $fileContent); + } + } + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition( + 'Move class to respect new location with respect to PSR-4 + follow up with class rename' + ); + } +} diff --git a/packages/Refactoring/src/Rector/FileSystem/MoveAndRenameNamespaceRector.php b/packages/Refactoring/src/Rector/FileSystem/MoveAndRenameNamespaceRector.php new file mode 100644 index 000000000000..ac349051d49c --- /dev/null +++ b/packages/Refactoring/src/Rector/FileSystem/MoveAndRenameNamespaceRector.php @@ -0,0 +1,89 @@ +fileRelocationResolver = $fileRelocationResolver; + $this->oldToNewNamespace = $oldToNewNamespace; + $this->namespaceMatcher = $namespaceMatcher; + } + + public function refactor(SmartFileInfo $smartFileInfo): void + { + $namespaceName = $this->resolveNamespaceName($smartFileInfo); + if ($namespaceName === null) { + return; + } + + $renamedNamespaceValueObject = $this->namespaceMatcher->matchRenamedNamespace( + $namespaceName, + $this->oldToNewNamespace + ); + + if ($renamedNamespaceValueObject === null) { + return; + } + + $newFileLocation = $this->fileRelocationResolver->resolveNewFileLocationFromRenamedNamespace( + $smartFileInfo, + $renamedNamespaceValueObject + ); + + // @todo + // create helping rename class rector.yaml + class_alias autoload file + // $this->renamedClassesCollector->addClassRename($oldClass, $newClass); + + $this->moveFile($smartFileInfo, $newFileLocation); + } + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition( + 'Move namespace to new location with respect to PSR-4 + follow up with files in the namespace move' + ); + } + + private function resolveNamespaceName(SmartFileInfo $smartFileInfo): ?string + { + $nodes = $this->parseFileInfoToNodesWithoutScope($smartFileInfo); + + /** @var Namespace_|null $namespace */ + $namespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class); + if ($namespace === null) { + return null; + } + + return $this->getName($namespace); + } +} diff --git a/packages/SymfonyPHPUnit/config/config.yaml b/packages/SymfonyPHPUnit/config/config.yaml index a52e8816fe98..9f10a8158059 100644 --- a/packages/SymfonyPHPUnit/config/config.yaml +++ b/packages/SymfonyPHPUnit/config/config.yaml @@ -5,3 +5,4 @@ services: Rector\SymfonyPHPUnit\: resource: '../src/' + exclude: '../src/{Rector/**/*Rector.php}' diff --git a/packages/TypeDeclaration/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php b/packages/TypeDeclaration/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php index 4a8a9774fad7..d8c009301791 100644 --- a/packages/TypeDeclaration/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php +++ b/packages/TypeDeclaration/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php @@ -73,7 +73,6 @@ protected function isChangeVendorLockedIn(ClassMethod $classMethod, int $paramPo $methodName = $this->getName($classMethod); // @todo extract to some "inherited parent method" service - /** @var string|null $parentClassName */ $parentClassName = $classMethod->getAttribute(AttributeKey::PARENT_CLASS_NAME); diff --git a/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php b/packages/TypeDeclaration/src/Rector/Property/CompleteVarDocTypePropertyRector.php similarity index 91% rename from packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php rename to packages/TypeDeclaration/src/Rector/Property/CompleteVarDocTypePropertyRector.php index be55b711be15..428a7166402d 100644 --- a/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php +++ b/packages/TypeDeclaration/src/Rector/Property/CompleteVarDocTypePropertyRector.php @@ -1,6 +1,6 @@ ------ - diff --git a/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/ParamTypeDeclarationRectorTest.php b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/ParamTypeDeclarationRectorTest.php index 8c0a5fc83325..f2256f7bd346 100644 --- a/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/ParamTypeDeclarationRectorTest.php +++ b/packages/TypeDeclaration/tests/Rector/FunctionLike/ParamTypeDeclarationRector/ParamTypeDeclarationRectorTest.php @@ -76,7 +76,6 @@ public function provideDataForTest(): iterable yield [__DIR__ . '/Fixture/dunglas/BazTrait.php.inc']; yield [__DIR__ . '/Fixture/dunglas/by_reference.php.inc']; yield [__DIR__ . '/Fixture/dunglas/Child.php.inc']; - yield [__DIR__ . '/Fixture/dunglas/Foo.php.inc']; yield [__DIR__ . '/Fixture/dunglas/functions.php.inc']; yield [__DIR__ . '/Fixture/dunglas/functions2.php.inc']; diff --git a/packages/Php/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php b/packages/TypeDeclaration/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php similarity index 86% rename from packages/Php/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php rename to packages/TypeDeclaration/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php index 07545e023b5e..a6d58d061907 100644 --- a/packages/Php/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php +++ b/packages/TypeDeclaration/tests/Rector/Property/CompleteVarDocTypePropertyRector/CompleteVarDocTypePropertyRectorTest.php @@ -1,10 +1,10 @@ removedFiles[$smartFileInfo->getRealPath()] = $smartFileInfo; } + public function addMovedFile(SmartFileInfo $oldFileInfo, string $newFileLocation, ?string $content = null): void + { + // keep original content if none provided + $content = $content ?: $oldFileInfo->getContents(); + + $this->movedFiles[] = new MovedClassValueObject( + $oldFileInfo->getRelativeFilePath(), + $newFileLocation, + $content + ); + } + /** * @return SmartFileInfo[] */ @@ -29,6 +47,14 @@ public function getRemovedFiles(): array return $this->removedFiles; } + /** + * @return MovedClassValueObject[] + */ + public function getMovedFiles(): array + { + return $this->movedFiles; + } + public function isFileRemoved(SmartFileInfo $smartFileInfo): bool { return isset($this->removedFiles[$smartFileInfo->getRealPath()]); diff --git a/src/Application/FileSystem/RemovedAndAddedFilesProcessor.php b/src/Application/FileSystem/RemovedAndAddedFilesProcessor.php index 7d2d322696bf..3e67990d72fa 100644 --- a/src/Application/FileSystem/RemovedAndAddedFilesProcessor.php +++ b/src/Application/FileSystem/RemovedAndAddedFilesProcessor.php @@ -3,6 +3,7 @@ namespace Rector\Application\FileSystem; use Rector\Configuration\Configuration; +use Rector\ValueObject\MovedClassValueObject; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Filesystem; @@ -47,6 +48,7 @@ public function run(): void { $this->processAddedFiles(); $this->processDeletedFiles(); + $this->processMovedFiles(); } private function processAddedFiles(): void @@ -74,4 +76,31 @@ private function processDeletedFiles(): void } } } + + private function processMovedFiles(): void + { + foreach ($this->removedAndAddedFilesCollector->getMovedFiles() as $movedClassValueObject) { + if ($this->configuration->isDryRun()) { + $this->printFileMoveWarning($movedClassValueObject, 'will be'); + } else { + $this->printFileMoveWarning($movedClassValueObject, 'was'); + + $this->filesystem->remove($movedClassValueObject->getOldPath()); + $this->filesystem->dumpFile( + $movedClassValueObject->getNewPath(), + $movedClassValueObject->getFileContent() + ); + } + } + } + + private function printFileMoveWarning(MovedClassValueObject $movedClassValueObject, string $verb): void + { + $this->symfonyStyle->warning(sprintf( + 'File "%s" %s moved to "%s"', + $movedClassValueObject->getOldPath(), + $verb, + $movedClassValueObject->getNewPath() + )); + } } diff --git a/src/Configuration/Configuration.php b/src/Configuration/Configuration.php index 8cb0571e160d..52f76d60af6f 100644 --- a/src/Configuration/Configuration.php +++ b/src/Configuration/Configuration.php @@ -7,6 +7,7 @@ use Rector\Console\Output\JsonOutputFormatter; use Rector\Exception\Rector\RectorNotFoundOrNotValidRectorClassException; use Rector\Rector\AbstractRector; +use Rector\Testing\PHPUnit\PHPUnitEnvironment; use Symfony\Component\Console\Input\InputInterface; use Symplify\PackageBuilder\Configuration\ConfigFileFinder; @@ -37,6 +38,11 @@ final class Configuration */ private $rule; + /** + * @var bool + */ + private $areAnyPhpRectorsLoaded = false; + /** * Needs to run in the start of the life cycle, since the rest of workflow uses it. */ @@ -104,6 +110,20 @@ public function getRule(): ?string return $this->rule; } + public function areAnyPhpRectorsLoaded(): bool + { + if (PHPUnitEnvironment::isPHPUnitRun()) { + return true; + } + + return $this->areAnyPhpRectorsLoaded; + } + + public function setAreAnyPhpRectorsLoaded(bool $areAnyPhpRectorsLoaded): void + { + $this->areAnyPhpRectorsLoaded = $areAnyPhpRectorsLoaded; + } + private function canShowProgressBar(InputInterface $input): bool { return $input->getOption(Option::OPTION_OUTPUT_FORMAT) !== JsonOutputFormatter::NAME; diff --git a/src/Console/Command/ProcessCommand.php b/src/Console/Command/ProcessCommand.php index e1f81ee71d5c..c4d4c3cc5d20 100644 --- a/src/Console/Command/ProcessCommand.php +++ b/src/Console/Command/ProcessCommand.php @@ -13,6 +13,7 @@ use Rector\Extension\ReportingExtensionRunner; use Rector\FileSystem\FilesFinder; use Rector\Guard\RectorGuard; +use Rector\PhpParser\NodeTraverser\RectorNodeTraverser; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -66,6 +67,11 @@ final class ProcessCommand extends AbstractCommand */ private $reportingExtensionRunner; + /** + * @var RectorNodeTraverser + */ + private $rectorNodeTraverser; + /** * @param string[] $fileExtensions */ @@ -78,6 +84,7 @@ public function __construct( RectorApplication $rectorApplication, OutputFormatterCollector $outputFormatterCollector, ReportingExtensionRunner $reportingExtensionRunner, + RectorNodeTraverser $rectorNodeTraverser, array $fileExtensions ) { $this->filesFinder = $phpFilesFinder; @@ -89,6 +96,7 @@ public function __construct( $this->fileExtensions = $fileExtensions; $this->outputFormatterCollector = $outputFormatterCollector; $this->reportingExtensionRunner = $reportingExtensionRunner; + $this->rectorNodeTraverser = $rectorNodeTraverser; parent::__construct(); } @@ -137,6 +145,7 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { $this->configuration->resolveFromInput($input); + $this->configuration->setAreAnyPhpRectorsLoaded((bool) $this->rectorNodeTraverser->getPhpRectorCount()); $this->rectorGuard->ensureSomeRectorsAreRegistered(); diff --git a/src/Exception/ShouldNotHappenException.php b/src/Exception/ShouldNotHappenException.php index 0e3fe42131c1..a85e3ebd6f7b 100644 --- a/src/Exception/ShouldNotHappenException.php +++ b/src/Exception/ShouldNotHappenException.php @@ -20,8 +20,8 @@ private function createDefaultMessageWithLocation(): string { $debugBacktrace = debug_backtrace(); - $class = $debugBacktrace[1]['class'] ?? null; - $function = $debugBacktrace[1]['function']; + $class = $debugBacktrace[2]['class'] ?? null; + $function = $debugBacktrace[2]['function']; $line = $debugBacktrace[1]['line']; $method = $class ? ($class . '::' . $function) : $function; diff --git a/src/Guard/RectorGuard.php b/src/Guard/RectorGuard.php index 80d45816a959..f2a759271e7e 100644 --- a/src/Guard/RectorGuard.php +++ b/src/Guard/RectorGuard.php @@ -28,7 +28,7 @@ public function __construct( public function ensureSomeRectorsAreRegistered(): void { - if ($this->rectorNodeTraverser->getRectorCount() > 0) { + if ($this->rectorNodeTraverser->getPhpRectorCount() > 0) { return; } diff --git a/src/Naming/NamespaceMatcher.php b/src/Naming/NamespaceMatcher.php new file mode 100644 index 000000000000..0b3a53dd4517 --- /dev/null +++ b/src/Naming/NamespaceMatcher.php @@ -0,0 +1,26 @@ + $newNamespace) { + if (Strings::startsWith($name, $oldNamespace)) { + return new RenamedNamespaceValueObject($name, $oldNamespace, $newNamespace); + } + } + + return null; + } +} diff --git a/src/PhpParser/Node/BetterNodeFinder.php b/src/PhpParser/Node/BetterNodeFinder.php index be9177de5b33..0621646a3bb4 100644 --- a/src/PhpParser/Node/BetterNodeFinder.php +++ b/src/PhpParser/Node/BetterNodeFinder.php @@ -179,6 +179,24 @@ public function findFirstPrevious(Node $node, callable $filter): ?Node return $this->findFirstPrevious($previousExpression, $filter); } + /** + * @param Node|Node[] $nodes + */ + public function findFirstClass($nodes): ?Class_ + { + /** @var Class_[] $classes */ + $classes = $this->findInstanceOf($nodes, Class_::class); + foreach ($classes as $class) { + if ($class->isAnonymous()) { + continue; + } + + return $class; + } + + return null; + } + /** * @param string[] $types */ diff --git a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php index 51327e3ac32d..e0ae12fc0331 100644 --- a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php @@ -52,19 +52,11 @@ public function traverse(array $nodes): array return parent::traverse($nodes); } - public function getRectorCount(): int + public function getPhpRectorCount(): int { return count($this->visitors); } - /** - * @return PhpRectorInterface[] - */ - public function getRectors(): array - { - return $this->visitors; - } - /** * Mostly used for testing */ diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index 021a91987e44..7ded9ae3d7d4 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -132,6 +132,9 @@ public function afterTraverse(array $nodes): array $nodes = $this->useAddingCommander->traverseNodes($nodes); } + // @todo name node importing + // @todo class like renaming + $this->tearDown(); return $nodes; @@ -142,11 +145,6 @@ protected function removeFile(SmartFileInfo $smartFileInfo): void $this->removedAndAddedFilesCollector->removeFile($smartFileInfo); } - protected function addFileWithContent(string $filePath, string $content): void - { - $this->removedAndAddedFilesCollector->addFileWithContent($filePath, $content); - } - protected function getNextExpression(Node $node): ?Node { $currentExpression = $node->getAttribute(AttributeKey::CURRENT_EXPRESSION); diff --git a/src/Rector/Class_/RenameClassRector.php b/src/Rector/Class_/RenameClassRector.php index d9b8e0c2a970..a66a64725627 100644 --- a/src/Rector/Class_/RenameClassRector.php +++ b/src/Rector/Class_/RenameClassRector.php @@ -230,7 +230,9 @@ private function getClassOfNamespaceToRefactor(Namespace_ $namespace): ?ClassLik return false; } - return isset($this->oldToNewClasses[$this->getName($node)]); + $classLikeName = $this->getName($node); + + return isset($this->oldToNewClasses[$classLikeName]); }); return $foundClass instanceof ClassLike ? $foundClass : null; diff --git a/src/Rector/Namespace_/RenameNamespaceRector.php b/src/Rector/Namespace_/RenameNamespaceRector.php index ce8012c7430e..ead64fd587c0 100644 --- a/src/Rector/Namespace_/RenameNamespaceRector.php +++ b/src/Rector/Namespace_/RenameNamespaceRector.php @@ -9,10 +9,12 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Use_; +use Rector\Naming\NamespaceMatcher; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Rector\AbstractRector; use Rector\RectorDefinition\ConfiguredCodeSample; use Rector\RectorDefinition\RectorDefinition; +use Rector\ValueObject\RenamedNamespaceValueObject; /** * @see \Rector\Tests\Rector\Namespace_\RenameNamespaceRector\RenameNamespaceRectorTest @@ -24,12 +26,18 @@ final class RenameNamespaceRector extends AbstractRector */ private $oldToNewNamespaces = []; + /** + * @var NamespaceMatcher + */ + private $namespaceMatcher; + /** * @param string[] $oldToNewNamespaces */ - public function __construct(array $oldToNewNamespaces = []) + public function __construct(NamespaceMatcher $namespaceMatcher, array $oldToNewNamespaces = []) { $this->oldToNewNamespaces = $oldToNewNamespaces; + $this->namespaceMatcher = $namespaceMatcher; } public function getDefinition(): RectorDefinition @@ -65,7 +73,8 @@ public function refactor(Node $node): ?Node return null; } - if (! $this->isNamespaceToChange($name)) { + $renamedNamespaceValueObject = $this->namespaceMatcher->matchRenamedNamespace($name, $this->oldToNewNamespaces); + if ($renamedNamespaceValueObject === null) { return null; } @@ -74,35 +83,28 @@ public function refactor(Node $node): ?Node } if ($node instanceof Namespace_) { - $newName = $this->resolveNewNameFromNode($name); + $newName = $renamedNamespaceValueObject->getNameInNewNamespace(); $node->name = new Name($newName); return $node; } if ($node instanceof Use_) { - $newName = $this->resolveNewNameFromNode($name); + $newName = $renamedNamespaceValueObject->getNameInNewNamespace(); $node->uses[0]->name = new Name($newName); return $node; } $newName = $this->isPartialNamespace($node) ? $this->resolvePartialNewName( - $node - ) : $this->resolveNewNameFromNode($name); - + $node, + $renamedNamespaceValueObject + ) : $renamedNamespaceValueObject->getNameInNewNamespace(); if ($newName === null) { return null; } - $node->parts = explode('\\', $newName); - - return $node; - } - - private function isNamespaceToChange(string $namespace): bool - { - return (bool) $this->getNewNamespaceForOldOne($namespace); + return new FullyQualified($newName); } /** @@ -128,13 +130,6 @@ private function isClassFullyQualifiedName(Node $node): bool return array_key_exists($newClassName, $this->oldToNewNamespaces); } - private function resolveNewNameFromNode(string $name): string - { - [$oldNamespace, $newNamespace] = $this->getNewNamespaceForOldOne($name); - - return str_replace($oldNamespace, $newNamespace, $name); - } - private function isPartialNamespace(Name $name): bool { $resolvedName = $name->getAttribute(AttributeKey::RESOLVED_NAME); @@ -149,42 +144,20 @@ private function isPartialNamespace(Name $name): bool return false; } - private function resolvePartialNewName(Name $name): ?string - { + private function resolvePartialNewName( + Name $name, + RenamedNamespaceValueObject $renamedNamespaceValueObject + ): ?string { $nodeName = $this->getName($name); if ($nodeName === null) { return null; } - $completeNewName = $this->resolveNewNameFromNode($nodeName); + $completeNewName = $renamedNamespaceValueObject->getNameInNewNamespace(); // first dummy implementation - improve $cutOffFromTheLeft = Strings::length($completeNewName) - Strings::length($name->toString()); return Strings::substring($completeNewName, $cutOffFromTheLeft); } - - /** - * @return string[] - */ - private function getNewNamespaceForOldOne(string $namespace): array - { - /** @var string $oldNamespace */ - foreach ($this->getOldToNewNamespaces() as $oldNamespace => $newNamespace) { - if (Strings::startsWith($namespace, $oldNamespace)) { - return [$oldNamespace, $newNamespace]; - } - } - - return []; - } - - /** - * @return string[] - */ - private function getOldToNewNamespaces(): array - { - krsort($this->oldToNewNamespaces); - return $this->oldToNewNamespaces; - } } diff --git a/src/ValueObject/MovedClassValueObject.php b/src/ValueObject/MovedClassValueObject.php new file mode 100644 index 000000000000..d5cc29674934 --- /dev/null +++ b/src/ValueObject/MovedClassValueObject.php @@ -0,0 +1,43 @@ +oldPath = $oldPath; + $this->newPath = $newPath; + $this->fileContent = $fileContent; + } + + public function getOldPath(): string + { + return $this->oldPath; + } + + public function getNewPath(): string + { + return $this->newPath; + } + + public function getFileContent(): string + { + return $this->fileContent; + } +} diff --git a/src/ValueObject/RenamedNamespaceValueObject.php b/src/ValueObject/RenamedNamespaceValueObject.php new file mode 100644 index 000000000000..aa10dbc4146e --- /dev/null +++ b/src/ValueObject/RenamedNamespaceValueObject.php @@ -0,0 +1,43 @@ +currentName = $currentNamespaceName; + $this->oldNamespace = $oldNamespace; + $this->newNamespace = $newNamespace; + } + + public function getNameInNewNamespace(): string + { + return str_replace($this->oldNamespace, $this->newNamespace, $this->currentName); + } + + public function getOldNamespace(): string + { + return $this->oldNamespace; + } + + public function getNewNamespace(): string + { + return $this->newNamespace; + } +} diff --git a/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/Fixture/fixture3.php.inc b/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/Fixture/fixture3.php.inc deleted file mode 100644 index 4e107d8bdaf5..000000000000 --- a/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/Fixture/fixture3.php.inc +++ /dev/null @@ -1,11 +0,0 @@ -engine = $engine; - } -} diff --git a/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/GetAndSetToMethodCallRectorTest.php b/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/GetAndSetToMethodCallRectorTest.php index ee7c10643cfb..32f56391a9c8 100644 --- a/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/GetAndSetToMethodCallRectorTest.php +++ b/tests/Rector/MagicDisclosure/GetAndSetToMethodCallRector/GetAndSetToMethodCallRectorTest.php @@ -24,7 +24,6 @@ public function provideDataForTest(): iterable { yield [__DIR__ . '/Fixture/get.php.inc']; yield [__DIR__ . '/Fixture/fixture2.php.inc']; - yield [__DIR__ . '/Fixture/fixture3.php.inc']; yield [__DIR__ . '/Fixture/klarka.php.inc']; } @@ -40,10 +39,6 @@ protected function getRectorsWithConfiguration(): array 'get' => 'getService', 'set' => 'addService', ], - 'Enlight_View_Default' => [ - 'get' => 'getService', - 'set' => 'addService', - ], Klarka::class => [ 'get' => 'get', ], diff --git a/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture.php.inc b/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture.php.inc index ad03d527f550..2c521140aac3 100644 --- a/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture.php.inc +++ b/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture.php.inc @@ -1,15 +1,21 @@ ------ - diff --git a/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture3.php.inc b/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture3.php.inc deleted file mode 100644 index b504f550550f..000000000000 --- a/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/fixture3.php.inc +++ /dev/null @@ -1,29 +0,0 @@ - ------ - diff --git a/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/skip.php.inc b/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/skip.php.inc new file mode 100644 index 000000000000..b43e3e23ed9a --- /dev/null +++ b/tests/Rector/MethodBody/ReturnThisRemoveRector/Fixture/skip.php.inc @@ -0,0 +1,18 @@ + [ '$classesToDefluent' => [ - 'Rector\Tests\Rector\MethodBody\ReturnThisRemoveRector\SomeClass', - 'Rector\Tests\Rector\MethodBody\ReturnThisRemoveRector\SomeClassWithReturnAnnotations', + 'Rector\Tests\Rector\MethodBody\ReturnThisRemoveRector\Fixture\SomeClass', + 'Rector\Tests\Rector\MethodBody\ReturnThisRemoveRector\Fixture\SomeClassWithReturnAnnotations', ], ], ];