diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/extends_exception.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/extends_exception.php.inc deleted file mode 100644 index acd7625e433..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/extends_exception.php.inc +++ /dev/null @@ -1,15 +0,0 @@ -message = $message; - $this->code = $code; - } -} diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/flip_position.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/flip_position.php.inc deleted file mode 100644 index 745069aba32..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/flip_position.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/skip_just_spread_arg.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/skip_just_spread_arg.php.inc deleted file mode 100644 index 11f59310e20..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/skip_just_spread_arg.php.inc +++ /dev/null @@ -1,13 +0,0 @@ - ------ - diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/union_parent_type.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/union_parent_type.php.inc deleted file mode 100644 index 0a8eeecc5b0..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Fixture/union_parent_type.php.inc +++ /dev/null @@ -1,35 +0,0 @@ - ------ - diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/ParamTypeByParentCallTypeRectorTest.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/ParamTypeByParentCallTypeRectorTest.php deleted file mode 100644 index 88d00b20e07..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/ParamTypeByParentCallTypeRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Source/ParentClassWithArraySpread.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Source/ParentClassWithArraySpread.php deleted file mode 100644 index 547e1e2a693..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector/Source/ParentClassWithArraySpread.php +++ /dev/null @@ -1,12 +0,0 @@ -rule(ParamTypeByParentCallTypeRector::class); - - $rectorConfig->phpVersion(PhpVersionFeature::UNION_TYPES); -}; diff --git a/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.php b/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.php deleted file mode 100644 index 6494e91dea2..00000000000 --- a/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.php +++ /dev/null @@ -1,86 +0,0 @@ -nodeNameResolver->getName($parentStaticCall->name); - if ($methodName === null) { - return null; - } - - // match current param to parent call position - $parentStaticCallArgPosition = $this->matchCallArgPosition($parentStaticCall, $param); - if ($parentStaticCallArgPosition === null) { - return null; - } - - return $this->resolveParentMethodParam($scope, $methodName, $parentStaticCallArgPosition); - } - - private function matchCallArgPosition(StaticCall $call, Param $param): int|null - { - $paramName = $this->nodeNameResolver->getName($param); - - foreach ($call->args as $argPosition => $arg) { - if (! $arg instanceof Arg) { - continue; - } - - if (! $arg->value instanceof Variable) { - continue; - } - - if (! $this->nodeNameResolver->isName($arg->value, $paramName)) { - continue; - } - - return $argPosition; - } - - return null; - } - - private function resolveParentMethodParam(Scope $scope, string $methodName, int $paramPosition): ?Param - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - foreach ($classReflection->getParents() as $parentClassReflection) { - if (! $parentClassReflection->hasMethod($methodName)) { - continue; - } - - $parentClassMethod = $this->astResolver->resolveClassMethod($parentClassReflection->getName(), $methodName); - if (! $parentClassMethod instanceof ClassMethod) { - continue; - } - - return $parentClassMethod->params[$paramPosition] ?? null; - } - - return null; - } -} diff --git a/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector.php index d7cfb206e0c..eea0180c536 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector.php @@ -5,35 +5,18 @@ namespace Rector\TypeDeclaration\Rector\ClassMethod; use PhpParser\Node; -use PhpParser\Node\Arg; -use PhpParser\Node\Expr\StaticCall; -use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\ClassMethod; -use PHPStan\Reflection\ClassReflection; -use Rector\Enum\ObjectReference; -use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\PhpParser\Node\BetterNodeFinder; -use Rector\PHPStan\ScopeFetcher; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; -use Rector\Reflection\ReflectionResolver; use Rector\RuleDoc\CodeSample\CodeSample; use Rector\RuleDoc\RuleDefinition; -use Rector\TypeDeclaration\NodeAnalyzer\CallerParamMatcher; /** - * @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\ParamTypeByParentCallTypeRector\ParamTypeByParentCallTypeRectorTest + * @deprecated This rule is deprecated, as it can add an invalid param type inferred from a single parent call usage. */ -final class ParamTypeByParentCallTypeRector extends AbstractRector +final class ParamTypeByParentCallTypeRector extends AbstractRector implements DeprecatedInterface { - public function __construct( - private readonly CallerParamMatcher $callerParamMatcher, - private readonly ReflectionResolver $reflectionResolver, - private readonly BetterNodeFinder $betterNodeFinder - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Change param type based on parent param type', [ @@ -89,132 +72,6 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - // no parent calls available - if ($node->extends === null) { - return null; - } - - $hasChanged = false; - - foreach ($node->getMethods() as $classMethod) { - if ($this->shouldSkip($classMethod)) { - continue; - } - - $parentStaticCall = $this->findParentStaticCall($classMethod); - if (! $parentStaticCall instanceof StaticCall) { - continue; - } - - $scope = ScopeFetcher::fetch($classMethod); - - foreach ($classMethod->params as $param) { - // already has type, skip - if ($param->type !== null) { - continue; - } - - if ($param->variadic) { - continue; - } - - if ($this->isParamUsedInSpreadArg($classMethod, $param)) { - continue; - } - - $parentParam = $this->callerParamMatcher->matchParentParam($parentStaticCall, $param, $scope); - if (! $parentParam instanceof Param) { - continue; - } - - if (! $parentParam->type instanceof Node) { - continue; - } - - // mimic type - $paramType = $parentParam->type; - - // original attributes have to removed to avoid tokens crashing from origin positions - $this->traverseNodesWithCallable($paramType, static function (Node $node): null { - $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); - return null; - }); - - $param->type = $paramType; - $hasChanged = true; - } - } - - if ($hasChanged) { - return $node; - } - - return null; - } - - private function findParentStaticCall(ClassMethod $classMethod): ?StaticCall - { - $classMethodName = $this->getName($classMethod); - - /** @var StaticCall[] $staticCalls */ - $staticCalls = $this->betterNodeFinder->findInstanceOf($classMethod, StaticCall::class); - - foreach ($staticCalls as $staticCall) { - if (! $this->isName($staticCall->class, ObjectReference::PARENT)) { - continue; - } - - if (! $this->isName($staticCall->name, $classMethodName)) { - continue; - } - - return $staticCall; - } - - return null; - } - - private function shouldSkip(ClassMethod $classMethod): bool - { - if (! $this->hasAtLeastOneParamWithoutType($classMethod)) { - return true; - } - - $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); - return ! $classReflection instanceof ClassReflection; - } - - private function isParamUsedInSpreadArg(ClassMethod $classMethod, Param $param): bool - { - /** @var Arg[] $args */ - $args = $this->betterNodeFinder->findInstancesOfScoped((array) $classMethod->stmts, Arg::class); - - $paramName = $this->getName($param); - foreach ($args as $arg) { - if (! $arg->unpack) { - continue; - } - - if ($arg->value instanceof Variable && $this->isName($arg->value, $paramName)) { - return true; - } - } - - return false; - } - - private function hasAtLeastOneParamWithoutType(ClassMethod $classMethod): bool - { - foreach ($classMethod->getParams() as $param) { - if ($param->variadic) { - continue; - } - - if ($param->type === null) { - return true; - } - } - - return false; + throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated', self::class)); } } diff --git a/src/Config/Level/TypeDeclarationLevel.php b/src/Config/Level/TypeDeclarationLevel.php index 5bcf947ec89..a4de4ffda4b 100644 --- a/src/Config/Level/TypeDeclarationLevel.php +++ b/src/Config/Level/TypeDeclarationLevel.php @@ -35,7 +35,6 @@ use Rector\TypeDeclaration\Rector\ClassMethod\NarrowObjectReturnTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictReturnsRector; use Rector\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector; -use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByParentCallTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\PrivateMethodReturnTypeFromStrictNewArrayRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNullableTypeRector; @@ -140,7 +139,6 @@ final class TypeDeclarationLevel // param AddMethodCallBasedStrictParamTypeRector::class, - ParamTypeByParentCallTypeRector::class, NarrowObjectReturnTypeRector::class,