diff --git a/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php b/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php index 6cc4e4e8..39f47742 100644 --- a/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php +++ b/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php @@ -65,7 +65,7 @@ public function processNode(Node $node, Scope $scope): ?array return null; } - $printedParamTypesString = $this->collectorMetadataPrinter->printParamTypesToString($node); + $printedParamTypesString = $this->collectorMetadataPrinter->printParamTypesToString($node, $classReflection->getName()); return [$classReflection->getName(), $methodName, $printedParamTypesString, $node->getLine()]; } } diff --git a/src/Printer/CollectorMetadataPrinter.php b/src/Printer/CollectorMetadataPrinter.php index 38915f8c..ef41d476 100644 --- a/src/Printer/CollectorMetadataPrinter.php +++ b/src/Printer/CollectorMetadataPrinter.php @@ -4,9 +4,12 @@ namespace Rector\TypePerfect\Printer; +use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Identifier; use PhpParser\Node\IntersectionType as NodeIntersectionType; +use PhpParser\Node\Name; +use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\UnionType; @@ -65,7 +68,7 @@ public function printArgTypesAsString(MethodCall $methodCall, Scope $scope): str return implode('|', $stringArgTypes); } - public function printParamTypesToString(ClassMethod $classMethod): string + public function printParamTypesToString(ClassMethod $classMethod, ?string $className): string { $printedParamTypes = []; foreach ($classMethod->params as $param) { @@ -74,14 +77,14 @@ public function printParamTypesToString(ClassMethod $classMethod): string continue; } - $paramType = $param->type; + $paramType = $this->transformSelfToClassName($param->type, $className); if ($paramType instanceof NullableType) { // unite to phpstan type $paramType = new UnionType([$paramType->type, new Identifier('null')]); } if ($paramType instanceof UnionType) { - $paramType = $this->resolveSortedUnionType($paramType); + $paramType = $this->resolveSortedUnionType($paramType, $className); } $printedParamType = $this->printerStandard->prettyPrint([$paramType]); @@ -94,19 +97,36 @@ public function printParamTypesToString(ClassMethod $classMethod): string return implode('|', $printedParamTypes); } - private function resolveSortedUnionType(UnionType $unionType): UnionType + private function transformSelfToClassName(Node $node, ?string $className): Node + { + if (! $node instanceof Name || $className === null) { + return $node; + } + + if ($node->toString() !== 'self') { + return $node; + } + + return new FullyQualified($className); + } + + private function resolveSortedUnionType(UnionType $unionType, ?string $className): UnionType { $typeNames = []; foreach ($unionType->types as $type) { if ($type instanceof NodeIntersectionType) { foreach ($type->types as $intersectionType) { + /** @var FullyQualified $intersectionType */ + $intersectionType = $this->transformSelfToClassName($intersectionType, $className); $typeNames[] = (string) $intersectionType; } continue; } + /** @var FullyQualified $type */ + $type = $this->transformSelfToClassName($type, $className); $typeNames[] = (string) $type; } diff --git a/src/Rules/NarrowPublicClassMethodParamTypeRule.php b/src/Rules/NarrowPublicClassMethodParamTypeRule.php index e27ed0ec..a9fe50ef 100644 --- a/src/Rules/NarrowPublicClassMethodParamTypeRule.php +++ b/src/Rules/NarrowPublicClassMethodParamTypeRule.php @@ -151,9 +151,9 @@ private function resolveUniqueArgTypesString( private function flattenCollectedData(array $methodCallablesByFilePath): array { $methodFirstClassCallables = []; - foreach ($methodCallablesByFilePath as $collectedData) { - foreach ($collectedData as $collectedItem) { - $methodFirstClassCallables[] = $collectedItem[0]; + foreach ($methodCallablesByFilePath as $methodCallables) { + foreach ($methodCallables as $methodCallable) { + $methodFirstClassCallables[] = $methodCallable[0]; } } diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/SkipSelf.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/SkipSelf.php new file mode 100644 index 00000000..f979c8e3 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/SkipSelf.php @@ -0,0 +1,17 @@ +takesSelf(new SkipSelf()); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php index 7478cd40..ebbc2f5c 100644 --- a/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php @@ -140,6 +140,10 @@ public static function provideData(): Iterator __DIR__ . '/Fixture/ThisPassedFromInterface.php', __DIR__ . '/Source/ExpectedThisType/CallByThisFromInterface.php', ], [[$argErrorMessage, 11]]]; + + yield [[ + __DIR__ . '/Fixture/SkipSelf.php', + ], []]; } /**