diff --git a/composer.json b/composer.json index 0a4f8f96b5c..3eeb99de162 100644 --- a/composer.json +++ b/composer.json @@ -58,9 +58,9 @@ "rector/rector-generator": "dev-main", "spatie/enum": "^3.13", "symplify/easy-ci": "^11.1.18", - "symplify/easy-coding-standard": "^11.1.18", - "symplify/phpstan-extensions": "^11.1.18", - "symplify/phpstan-rules": "^11.1.28", + "symplify/easy-coding-standard": "^11.3", + "symplify/phpstan-extensions": "^11.2", + "symplify/phpstan-rules": "^12.0", "symplify/rule-doc-generator": "^11.1.18", "symplify/vendor-patches": "^11.2.3", "tomasvotruba/cognitive-complexity": "^0.0.1", diff --git a/phpstan.neon b/phpstan.neon index 59c6f29912a..b4579c99cb9 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -89,6 +89,7 @@ parameters: - message: '#Array (with keys|destruct) is not allowed\. Use value object to pass data instead#' path: rules/Php70/EregToPcreTransformer.php + - message: '#Use explicit return value over magic &reference#' path: rules/Php70/EregToPcreTransformer.php @@ -102,10 +103,6 @@ parameters: - '#Method (.*?) should return array but returns array#' - - '#Access to an undefined property PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Expr\\Variable\:\:\$name#' - - - '#PhpParser\\Node\\Expr\\Error\|PhpParser\\Node\\Expr\\Variable given#' - - message: '#There should be no empty class#' paths: @@ -168,7 +165,6 @@ parameters: - '#Method Rector\\NodeTypeResolver\\PHPStan\\Type\\TypeFactory\:\:uniquateTypes\(\) should return array but returns array#' # resolve later - - '#Method "(.*?)\(\)" only calling another method call and has no added value\. Use the inlined call instead#' - '#Method "processRenameVariable\(\)" returns bool type, so the name should start with is/has/was#' - '#Method "resolveObjectType\(\)" returns bool type, so the name should start with is/has/was#' @@ -373,11 +369,6 @@ parameters: message: '#Call to static method Webmozart\\Assert\\Assert\:\:allString\(\) with array> will always evaluate to true#' path: packages/Config/RectorConfig.php - # hash key - - - path: rules/Renaming/NodeManipulator/ClassRenamer.php - message: '#Use separate function calls with readable variable names#' - - '#Cognitive complexity for "Rector\\NodeTypeResolver\\PHPStan\\Scope\\PHPStanNodeScopeResolver\:\:processNodes\(\)" is \d+, keep it under 10#' # depends on falsy docs @@ -488,24 +479,6 @@ parameters: # part of tests - '#Call to method PHPUnit\\Framework\\Assert\:\:assertIsInt\(\) with 50200\|50300\|50400\|50500\|50600\|70000\|70100\|70200\|70300\|70400\|80000\|80100\|80200\|100000 will always evaluate to true#' - - - message: '#Method call return value that should be used, but is not#' - paths: - - src/Console/Output/RectorOutputStyle.php - - rules/Compatibility/NodeFactory/ConstructorClassMethodFactory.php - - src/Application/ChangedNodeScopeRefresher.php - - rules/TypeDeclaration/TypeNormalizer.php - - rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php - - rules/Removing/NodeManipulator/ComplexNodeRemover.php - - rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.php - - packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php - - packages/PhpDocParser/PhpDocParser/PhpDocNodeTraverser.php - - - - message: '#Method call return value that should be used, but is not#' - path: src/PhpParser/Node/NodeFactory.php - count: 1 - # false postive, on trait use in multiple classes - message: '#Method name "(.*?)Attribute\(\)" is used in multiple traits\. Make it unique to avoid conflicts#' @@ -649,10 +622,6 @@ parameters: - src/DependencyInjection/DefinitionFinder.php # changelog generator - - - message: '#Do not use chained method calls\. Put each on separated lines#' - path: utils/ChangelogGenerator/GithubApiCaller.php - - message: '#Anonymous (variable|variables) in#' path: utils/ChangelogGenerator @@ -699,10 +668,6 @@ parameters: message: '#Method call return value that should be used, but is not#' path: packages-tests/BetterPhpDocParser/PhpDocInfo/PhpDocInfo/PhpDocInfoTest.php - - - message: '#"Tests" namespace cannot be used outside of "tests" directory#' - path: utils-tests - # trusted items - '#Parameter \#1 \$nodes of method PhpParser\\PrettyPrinterAbstract\:\:pCommaSeparatedMultiline\(\) expects array, array given#' @@ -766,15 +731,6 @@ parameters: message: '#Method "renameVariableInFunctionLike\(\)" returns bool type, so the name should start with is/has/was#' path: rules/Naming/VariableRenamer.php - - - message: '#Method call return value that should be used, but is not#' - paths: - - rules/Naming/ParamRenamer/ParamRenamer.php - - rules/Naming/PropertyRenamer/PropertyPromotionRenamer.php - - rules/Naming/Rector/Assign/RenameVariableToMatchMethodCallReturnTypeRector.php - - rules/Naming/Rector/ClassMethod/RenameVariableToMatchNewTypeRector.php - - rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php - # next to resolve - '#Cognitive complexity for "Rector\\EarlyReturn\\Rector\\Return_\\PreparedValueToEarlyReturnRector\:\:refactor\(\)" is 11, keep it under 10#' - '#Cognitive complexity for "Rector\\CodeQuality\\Rector\\Foreach_\\SimplifyForeachToCoalescingRector\:\:refactor\(\)" is 16, keep it under 10#' @@ -786,10 +742,6 @@ parameters: - '#(Matching|Fetching) deprecated class constant (NEXT_NODE|PREVIOUS_NODE) of class Rector\\NodeTypeResolver\\Node\\AttributeKey#' - '#Property Rector\\Core\\Contract\\PhpParser\\Node\\StmtsAwareInterface\:\:\$stmts \(array\|null\) does not accept array#' - # make autoload of php-parser in rector first - - '#but class PhpParser\\Node\\Stmt\\Expression is not generic#' - - '#Parameter \#3 \$assign of method Rector\\CodeQuality\\Rector\\FunctionLike\\SimplifyUselessVariableRector\:\:processSimplifyUselessVariable\(\) expects PhpParser\\Node\\Expr\\Assign\|PhpParser\\Node\\Expr\\AssignOp, PhpParser\\Node\\Expr given#' - # deprecated - '#Register "Rector\\Php80\\Rector\\FunctionLike\\UnionTypesRector" service to "php80\.php" config set#' - '#Fetching class constant class of deprecated class Rector\\CodeQuality\\Rector\\ClassMethod\\NarrowUnionTypeDocRector#' @@ -800,12 +752,14 @@ parameters: message: '#Do not use static property#' path: src/Kernel/RectorKernel.php - # this is due to compare VersionResolver::PACKAGE_VERSION to verify on rector-src - - - message: '#Public method "Rector\\Core\\Kernel\\RectorKernel\:\:clearCache\(\)" is never used#' - path: src/Kernel/RectorKernel.php - # '@package_version@' compare with '@package_version@' to verify on rector-src - message: '#Strict comparison using \!\=\= between .* and .* will always evaluate to false#' path: src/Kernel/RectorKernel.php + + # expression generics + - '#PHPDoc tag @return contains generic type PhpParser\\Node\\Stmt\\Expression but class PhpParser\\Node\\Stmt\\Expression is not generic#' + - '#PHPDoc tag @var for variable \$previousStmt contains generic type PhpParser\\Node\\Stmt\\Expression but class PhpParser\\Node\\Stmt\\Expression is not generic#' + - '#Parameter \#3 \$assign of method Rector\\CodeQuality\\Rector\\FunctionLike\\SimplifyUselessVariableRector\:\:processSimplifyUselessVariable\(\) expects PhpParser\\Node\\Expr\\Assign\|PhpParser\\Node\\Expr\\AssignOp, PhpParser\\Node\\Expr given#' + - '#Anonymous variable in a `\$stmtsAware\->stmts\[\$key \- 1\]\->\.\.\.\(\)` method call can lead to false dead methods\. Make sure the variable type is known#' + - '#Anonymous variable in a `\$parentNode\->stmts\[\$key\]\->\.\.\.\(\)` method call can lead to false dead methods\. Make sure the variable type is known#' diff --git a/rules/Naming/Guard/BreakingVariableRenameGuard.php b/rules/Naming/Guard/BreakingVariableRenameGuard.php index fb79a03a80d..62ef1268a1b 100644 --- a/rules/Naming/Guard/BreakingVariableRenameGuard.php +++ b/rules/Naming/Guard/BreakingVariableRenameGuard.php @@ -9,6 +9,7 @@ use PhpParser\Node\Expr; use PhpParser\Node\Expr\ArrowFunction; use PhpParser\Node\Expr\Closure; +use PhpParser\Node\Expr\Error; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; @@ -113,6 +114,10 @@ public function shouldSkipParam( return true; } + if ($param->var instanceof Error) { + return true; + } + if ($this->isVariableAlreadyDefined($param->var, $currentName)) { return true; } diff --git a/rules/Naming/PropertyRenamer/PropertyPromotionRenamer.php b/rules/Naming/PropertyRenamer/PropertyPromotionRenamer.php index 3979359a464..fb835a35d3a 100644 --- a/rules/Naming/PropertyRenamer/PropertyPromotionRenamer.php +++ b/rules/Naming/PropertyRenamer/PropertyPromotionRenamer.php @@ -4,6 +4,8 @@ namespace Rector\Naming\PropertyRenamer; +use PhpParser\Node\Expr\Error; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassLike; @@ -85,6 +87,10 @@ private function renameParamVarNameAndVariableUsage( string $desiredPropertyName, Param $param ): void { + if ($param->var instanceof Error) { + return; + } + $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); $currentParamName = $this->nodeNameResolver->getName($param); @@ -98,7 +104,7 @@ private function renameParamVarNameAndVariableUsage( /** @var string $paramVarName */ $paramVarName = $param->var->name; $this->renameParamDoc($classMethodPhpDocInfo, $param, $paramVarName, $desiredPropertyName); - $param->var->name = $desiredPropertyName; + $param->var = new Variable($desiredPropertyName); $this->variableRenamer->renameVariableInFunctionLike($classMethod, $paramVarName, $desiredPropertyName); } diff --git a/rules/Naming/ValueObjectFactory/ParamRenameFactory.php b/rules/Naming/ValueObjectFactory/ParamRenameFactory.php index 4487fde4992..46d45bdc5b2 100644 --- a/rules/Naming/ValueObjectFactory/ParamRenameFactory.php +++ b/rules/Naming/ValueObjectFactory/ParamRenameFactory.php @@ -6,6 +6,7 @@ use PhpParser\Node\Expr\ArrowFunction; use PhpParser\Node\Expr\Closure; +use PhpParser\Node\Expr\Error; use PhpParser\Node\FunctionLike; use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; @@ -25,6 +26,10 @@ public function __construct( public function createFromResolvedExpectedName(Param $param, string $expectedName): ?ParamRename { + if ($param->var instanceof Error) { + return null; + } + /** @var ClassMethod|Function_|Closure|ArrowFunction|null $functionLike */ $functionLike = $this->betterNodeFinder->findParentType($param, FunctionLike::class); if ($functionLike === null) { diff --git a/rules/Php72/NodeManipulator/ClosureNestedUsesDecorator.php b/rules/Php72/NodeManipulator/ClosureNestedUsesDecorator.php index 183dd5976ed..73f6f259d89 100644 --- a/rules/Php72/NodeManipulator/ClosureNestedUsesDecorator.php +++ b/rules/Php72/NodeManipulator/ClosureNestedUsesDecorator.php @@ -59,6 +59,10 @@ public function applyNestedUses(Closure $anonymousFunctionNode, Variable $useVar private function collectUsesEqual(Closure $closure, array $uses, Variable $useVariable): array { foreach ($closure->params as $param) { + if (! $param->var instanceof Variable) { + continue; + } + if ($this->nodeComparator->areNodesEqual($param->var, $useVariable)) { $uses[] = new ClosureUse($param->var); } diff --git a/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php b/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php index 4e085eb62a0..8495f1903b4 100644 --- a/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php +++ b/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; use PhpParser\Node\NullableType; use PhpParser\Node\Param; @@ -166,7 +167,8 @@ public function refactor(Node $node): ?Node } // property name has higher priority - $param->var->name = $this->getName($property); + $paramName = $this->getName($property); + $param->var = new Variable($paramName); $param->flags = $property->flags; // Copy over attributes of the "old" property diff --git a/src/Exception/Cache/StaleContainerCacheException.php b/src/Exception/Cache/StaleContainerCacheException.php index 508c407b0c0..c9b18da3e14 100644 --- a/src/Exception/Cache/StaleContainerCacheException.php +++ b/src/Exception/Cache/StaleContainerCacheException.php @@ -5,4 +5,7 @@ namespace Rector\Core\Exception\Cache; use RuntimeException; -final class StaleContainerCacheException extends RuntimeException {} + +final class StaleContainerCacheException extends RuntimeException +{ +} diff --git a/src/Kernel/CacheInvalidatingContainer.php b/src/Kernel/CacheInvalidatingContainer.php index c0bc0adc13f..fac31607e85 100644 --- a/src/Kernel/CacheInvalidatingContainer.php +++ b/src/Kernel/CacheInvalidatingContainer.php @@ -4,16 +4,17 @@ namespace Rector\Core\Kernel; -use Throwable; -use UnitEnum; use Rector\Core\Exception\Cache\StaleContainerCacheException; use Symfony\Component\DependencyInjection\ContainerInterface; +use Throwable; +use UnitEnum; -final class CacheInvalidatingContainer implements ContainerInterface { +final class CacheInvalidatingContainer implements ContainerInterface +{ public function __construct( private readonly ContainerInterface $container - ) - {} + ) { + } public function set(string $id, ?object $service): void { diff --git a/src/NodeAnalyzer/ParamAnalyzer.php b/src/NodeAnalyzer/ParamAnalyzer.php index bbf18a93ac2..09ab53f4816 100644 --- a/src/NodeAnalyzer/ParamAnalyzer.php +++ b/src/NodeAnalyzer/ParamAnalyzer.php @@ -9,6 +9,7 @@ use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\ConstFetch; +use PhpParser\Node\Expr\Error; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\Variable; @@ -42,6 +43,10 @@ public function isParamUsedInClassMethod(ClassMethod $classMethod, Param $param) { $isParamUsed = false; + if ($param->var instanceof Error) { + return false; + } + $this->simpleCallableNodeTraverser->traverseNodesWithCallable($classMethod->stmts, function (Node $node) use ( &$isParamUsed, $param diff --git a/src/NodeManipulator/AssignManipulator.php b/src/NodeManipulator/AssignManipulator.php index ed7ba49103e..29846ff3567 100644 --- a/src/NodeManipulator/AssignManipulator.php +++ b/src/NodeManipulator/AssignManipulator.php @@ -79,7 +79,7 @@ public function isLeftPartOfAssign(Node $node): bool * * Compare same node to ensure php_doc_info info not be checked */ - return $this->nodeComparator->areSameNode($parentNode->var, $node); + return $this->nodeComparator->areSameNode($parentNode->var, $node); } if ($this->isOnArrayDestructuring($parentNode)) { diff --git a/src/NodeManipulator/Dependency/DependencyClassMethodDecorator.php b/src/NodeManipulator/Dependency/DependencyClassMethodDecorator.php index 9cbfef7c755..f16beda57fc 100644 --- a/src/NodeManipulator/Dependency/DependencyClassMethodDecorator.php +++ b/src/NodeManipulator/Dependency/DependencyClassMethodDecorator.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; @@ -191,8 +192,8 @@ private function incrementParamIfExists( } if ($name !== $newName) { - $param->var = clone $param->var; - $param->var->name = $name; + // $param->var = clone $param->var; + $param->var = new Variable($name); } }