diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc new file mode 100644 index 00000000000..d6f93feb14d --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Fixture/skip_anonymous_class_this_return.php.inc @@ -0,0 +1,27 @@ +id; + } + + public function setId(int $id): Email + { + $this->id = $id; + + return $this; + } + }; + } +} diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php new file mode 100644 index 00000000000..2a9eac4545b --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector/Source/Email.php @@ -0,0 +1,9 @@ + preserve shape. - $allConstantArrayTypes = array_reduce($types, fn ($c, $t): bool => $c && $t instanceof ConstantArrayType, true); - if ($allConstantArrayTypes) { - /** @var ConstantArrayType[] $consts */ - $consts = $types; - - // Compare key sets (by stringified key types) - $firstKeys = array_map( - fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()), - $consts[0]->getKeyTypes() - ); - foreach ($consts as $c) { - $keys = array_map( - fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()), - $c->getKeyTypes() - ); - if ($keys !== $firstKeys) { - $allConstantArrayTypes = false; - break; - } - } - - if ($allConstantArrayTypes) { - $resultKeyTypes = $consts[0]->getKeyTypes(); - $valueColumns = []; - foreach ($consts as $const) { - $valueColumns[] = $const->getValueTypes(); - } - - $resultValueTypes = []; - foreach (array_keys($resultKeyTypes) as $i) { - $col = array_column($valueColumns, $i); - $resultValueTypes[] = $this->sharedArrayStructure(...$col); - } - - return new ConstantArrayType($resultKeyTypes, $resultValueTypes); - } - } - // Generic ArrayType path: reconcile key type + recurse into item types /** @var ArrayType[] $types */ /** @var ArrayType[] $arrayTypes */ diff --git a/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php b/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php index 39e5185d633..401e01d7d92 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php @@ -304,6 +304,14 @@ private function getActualReturnedClass(ClassMethod $classMethod): ?string $className = $classNames[0]; + // skip anonymous classes, they have no usable name + if ($this->reflectionProvider->hasClass($className)) { + $returnedClassReflection = $this->reflectionProvider->getClass($className); + if ($returnedClassReflection->isAnonymous()) { + return null; + } + } + if ($returnedClass === null) { $returnedClass = $className; } elseif ($returnedClass !== $className) {