Skip to content

Commit 22f755c

Browse files
committed
Optimizations
1 parent 35a374a commit 22f755c

File tree

1 file changed

+56
-32
lines changed

1 file changed

+56
-32
lines changed

src/Type/ObjectType.php

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@
3737
use PHPStan\Type\Traits\NonGenericTypeTrait;
3838
use PHPStan\Type\Traits\UndecidedComparisonTypeTrait;
3939
use Traversable;
40+
use function array_key_exists;
4041
use function array_keys;
4142
use function array_map;
4243
use function array_values;
4344
use function count;
45+
use function implode;
4446
use function in_array;
4547
use function sprintf;
4648
use function strtolower;
@@ -71,10 +73,10 @@ class ObjectType implements TypeWithClassName, SubtractableType
7173
/** @var array<string, array<string, array<string, UnresolvedPropertyPrototypeReflection>>> */
7274
private static array $properties = [];
7375

74-
/** @var array<string, array<string, self>> */
76+
/** @var array<string, array<string, self|null>> */
7577
private static array $ancestors = [];
7678

77-
/** @var array<string, self> */
79+
/** @var array<string, self|null> */
7880
private array $currentAncestors = [];
7981

8082
/** @api */
@@ -436,6 +438,16 @@ private function describeCache(): string
436438
}
437439

438440
$description = $this->className;
441+
442+
if ($this instanceof GenericObjectType) {
443+
$description .= '<';
444+
$typeDescriptions = [];
445+
foreach ($this->getTypes() as $type) {
446+
$typeDescriptions[] = $type->describe(VerbosityLevel::cache());
447+
}
448+
$description .= '<' . implode(', ', $typeDescriptions) . '>';
449+
}
450+
439451
if ($this->subtractedType !== null) {
440452
$description .= sprintf('~%s', $this->subtractedType->describe(VerbosityLevel::cache()));
441453
}
@@ -1019,35 +1031,41 @@ public function getTypeWithoutSubtractedType(): Type
10191031

10201032
public function changeSubtractedType(?Type $subtractedType): Type
10211033
{
1022-
$classReflection = $this->getClassReflection();
1023-
if ($classReflection !== null && $classReflection->isEnum() && $subtractedType !== null) {
1024-
$cases = [];
1025-
foreach (array_keys($classReflection->getEnumCases()) as $name) {
1026-
$cases[$name] = new EnumCaseObjectType($classReflection->getName(), $name);
1027-
}
1028-
1029-
foreach (TypeUtils::flattenTypes($subtractedType) as $subType) {
1030-
if (!$subType instanceof EnumCaseObjectType) {
1031-
return new self($this->className, $subtractedType);
1034+
if ($subtractedType !== null) {
1035+
$classReflection = $this->getClassReflection();
1036+
if ($classReflection !== null && $classReflection->isEnum()) {
1037+
$cases = [];
1038+
foreach (array_keys($classReflection->getEnumCases()) as $name) {
1039+
$cases[$name] = new EnumCaseObjectType($classReflection->getName(), $name);
10321040
}
10331041

1034-
if ($subType->getClassName() !== $this->getClassName()) {
1035-
return new self($this->className, $subtractedType);
1042+
foreach (TypeUtils::flattenTypes($subtractedType) as $subType) {
1043+
if (!$subType instanceof EnumCaseObjectType) {
1044+
return new self($this->className, $subtractedType);
1045+
}
1046+
1047+
if ($subType->getClassName() !== $this->getClassName()) {
1048+
return new self($this->className, $subtractedType);
1049+
}
1050+
1051+
unset($cases[$subType->getEnumCaseName()]);
10361052
}
10371053

1038-
unset($cases[$subType->getEnumCaseName()]);
1039-
}
1054+
$cases = array_values($cases);
1055+
if (count($cases) === 0) {
1056+
return new NeverType();
1057+
}
10401058

1041-
$cases = array_values($cases);
1042-
if (count($cases) === 0) {
1043-
return new NeverType();
1044-
}
1059+
if (count($cases) === 1) {
1060+
return $cases[0];
1061+
}
10451062

1046-
if (count($cases) === 1) {
1047-
return $cases[0];
1063+
return new UnionType(array_values($cases));
10481064
}
1065+
}
10491066

1050-
return new UnionType(array_values($cases));
1067+
if ($this->subtractedType === null && $subtractedType === null) {
1068+
return $this;
10511069
}
10521070

10531071
return new self($this->className, $subtractedType);
@@ -1110,26 +1128,32 @@ public function getClassReflection(): ?ClassReflection
11101128
*/
11111129
public function getAncestorWithClassName(string $className): ?TypeWithClassName
11121130
{
1113-
if (isset($this->currentAncestors[$className])) {
1131+
if (array_key_exists($className, $this->currentAncestors)) {
11141132
return $this->currentAncestors[$className];
11151133
}
11161134

1117-
$thisReflection = $this->getClassReflection();
1118-
if ($thisReflection === null) {
1119-
return null;
1135+
$description = $this->describeCache();
1136+
if (
1137+
array_key_exists($description, self::$ancestors)
1138+
&& array_key_exists($className, self::$ancestors[$description])
1139+
) {
1140+
return self::$ancestors[$description][$className];
11201141
}
11211142

1122-
$description = $this->describeCache() . '-' . $thisReflection->getCacheKey();
1123-
if (isset(self::$ancestors[$description][$className])) {
1124-
return self::$ancestors[$description][$className];
1143+
if ($this->className === $className) {
1144+
return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = $this;
11251145
}
11261146

11271147
$reflectionProvider = ReflectionProviderStaticAccessor::getInstance();
11281148
if (!$reflectionProvider->hasClass($className)) {
1129-
return null;
1149+
return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null;
11301150
}
11311151
$theirReflection = $reflectionProvider->getClass($className);
11321152

1153+
$thisReflection = $this->getClassReflection();
1154+
if ($thisReflection === null) {
1155+
return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null;
1156+
}
11331157
if ($theirReflection->getName() === $thisReflection->getName()) {
11341158
return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = $this;
11351159
}
@@ -1149,7 +1173,7 @@ public function getAncestorWithClassName(string $className): ?TypeWithClassName
11491173
}
11501174
}
11511175

1152-
return null;
1176+
return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null;
11531177
}
11541178

11551179
private function getParent(): ?ObjectType

0 commit comments

Comments
 (0)