Skip to content

Commit dce1bcb

Browse files
authored
[TypeDeclaration] Skip anonymous class return in NarrowObjectReturnTypeRector (#8131)
* [TypeDeclaration] Skip anonymous class in NarrowObjectReturnTypeRector * [Privatization] Narrow ConstantArrayType filter to satisfy PHPStan native type check
1 parent 7be5413 commit dce1bcb

4 files changed

Lines changed: 44 additions & 41 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NarrowObjectReturnTypeRector\Fixture;
4+
5+
use Rector\Tests\TypeDeclaration\Rector\ClassMethod\NarrowObjectReturnTypeRector\Source\Email;
6+
7+
final class EmailFactory
8+
{
9+
private function createEmail(): Email
10+
{
11+
return new class extends Email {
12+
private int $id = 0;
13+
14+
public function getId(): int
15+
{
16+
return $this->id;
17+
}
18+
19+
public function setId(int $id): Email
20+
{
21+
$this->id = $id;
22+
23+
return $this;
24+
}
25+
};
26+
}
27+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NarrowObjectReturnTypeRector\Source;
6+
7+
class Email
8+
{
9+
}

rules/Privatization/TypeManipulator/ArrayTypeLeastCommonDenominatorResolver.php

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
namespace Rector\Privatization\TypeManipulator;
66

77
use PHPStan\Type\ArrayType;
8-
use PHPStan\Type\Constant\ConstantArrayType;
98
use PHPStan\Type\MixedType;
109
use PHPStan\Type\NeverType;
1110
use PHPStan\Type\Type;
1211
use PHPStan\Type\TypeCombinator;
13-
use PHPStan\Type\VerbosityLevel;
1412

1513
/**
1614
* Made with GPT-5
@@ -37,45 +35,6 @@ public function sharedArrayStructure(Type ...$types): Type
3735
}
3836
}
3937

40-
// If all are ConstantArrayType and have the *same* ordered key list -> preserve shape.
41-
$allConstantArrayTypes = array_reduce($types, fn ($c, $t): bool => $c && $t instanceof ConstantArrayType, true);
42-
if ($allConstantArrayTypes) {
43-
/** @var ConstantArrayType[] $consts */
44-
$consts = $types;
45-
46-
// Compare key sets (by stringified key types)
47-
$firstKeys = array_map(
48-
fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()),
49-
$consts[0]->getKeyTypes()
50-
);
51-
foreach ($consts as $c) {
52-
$keys = array_map(
53-
fn (Type $type): string => $type->describe(VerbosityLevel::typeOnly()),
54-
$c->getKeyTypes()
55-
);
56-
if ($keys !== $firstKeys) {
57-
$allConstantArrayTypes = false;
58-
break;
59-
}
60-
}
61-
62-
if ($allConstantArrayTypes) {
63-
$resultKeyTypes = $consts[0]->getKeyTypes();
64-
$valueColumns = [];
65-
foreach ($consts as $const) {
66-
$valueColumns[] = $const->getValueTypes();
67-
}
68-
69-
$resultValueTypes = [];
70-
foreach (array_keys($resultKeyTypes) as $i) {
71-
$col = array_column($valueColumns, $i);
72-
$resultValueTypes[] = $this->sharedArrayStructure(...$col);
73-
}
74-
75-
return new ConstantArrayType($resultKeyTypes, $resultValueTypes);
76-
}
77-
}
78-
7938
// Generic ArrayType path: reconcile key type + recurse into item types
8039
/** @var ArrayType[] $types */
8140
/** @var ArrayType[] $arrayTypes */

rules/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@ private function getActualReturnedClass(ClassMethod $classMethod): ?string
304304

305305
$className = $classNames[0];
306306

307+
// skip anonymous classes, they have no usable name
308+
if ($this->reflectionProvider->hasClass($className)) {
309+
$returnedClassReflection = $this->reflectionProvider->getClass($className);
310+
if ($returnedClassReflection->isAnonymous()) {
311+
return null;
312+
}
313+
}
314+
307315
if ($returnedClass === null) {
308316
$returnedClass = $className;
309317
} elseif ($returnedClass !== $className) {

0 commit comments

Comments
 (0)