From 4c7046ef681d05e81f5ad866230582a0009272b9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 20 Feb 2023 10:25:17 +0100 Subject: [PATCH] Type::getObjectClassReflections() --- phpstan-baseline.neon | 8 ++++---- src/Rules/Api/ApiInstanceofTypeRule.php | 2 +- src/Type/Accessory/AccessoryArrayListType.php | 5 +++++ src/Type/Accessory/AccessoryLiteralStringType.php | 5 +++++ src/Type/Accessory/AccessoryNonEmptyStringType.php | 5 +++++ src/Type/Accessory/AccessoryNonFalsyStringType.php | 5 +++++ src/Type/Accessory/AccessoryNumericStringType.php | 5 +++++ src/Type/Accessory/HasMethodType.php | 5 +++++ src/Type/Accessory/HasOffsetType.php | 5 +++++ src/Type/Accessory/HasOffsetValueType.php | 5 +++++ src/Type/Accessory/HasPropertyType.php | 5 +++++ src/Type/Accessory/NonEmptyArrayType.php | 5 +++++ src/Type/Accessory/OversizedArrayType.php | 5 +++++ src/Type/ArrayType.php | 5 +++++ src/Type/CallableType.php | 5 +++++ src/Type/ClosureType.php | 7 ++++++- src/Type/FloatType.php | 5 +++++ src/Type/IntersectionType.php | 12 ++++++++++++ src/Type/IterableType.php | 5 +++++ src/Type/JustNullableTypeTrait.php | 5 +++++ src/Type/MixedType.php | 5 +++++ src/Type/NeverType.php | 5 +++++ src/Type/NullType.php | 5 +++++ src/Type/ObjectType.php | 10 ++++++++++ src/Type/ObjectWithoutClassType.php | 5 +++++ src/Type/OffsetAccessType.php | 5 +++++ src/Type/StaticType.php | 5 +++++ src/Type/StrictMixedType.php | 5 +++++ src/Type/Traits/LateResolvableTypeTrait.php | 5 +++++ src/Type/Type.php | 6 ++++++ src/Type/UnionType.php | 5 +++++ src/Type/VoidType.php | 5 +++++ .../PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php | 6 +++--- 33 files changed, 172 insertions(+), 9 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3fe2c198a8..ace733e310 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -484,7 +484,7 @@ parameters: path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -904,7 +904,7 @@ parameters: path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/GenericObjectType.php @@ -1210,7 +1210,7 @@ parameters: path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Type/Php/DsMapDynamicReturnTypeExtension.php @@ -1423,7 +1423,7 @@ parameters: path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Type/TypeUtils.php diff --git a/src/Rules/Api/ApiInstanceofTypeRule.php b/src/Rules/Api/ApiInstanceofTypeRule.php index 5fd222d53d..cec11513e4 100644 --- a/src/Rules/Api/ApiInstanceofTypeRule.php +++ b/src/Rules/Api/ApiInstanceofTypeRule.php @@ -51,7 +51,7 @@ class ApiInstanceofTypeRule implements Rule { private const MAP = [ - TypeWithClassName::class => 'Type::getObjectClassNames()', + TypeWithClassName::class => 'Type::getObjectClassNames() or Type::getObjectClassReflections()', EnumCaseObjectType::class => 'Type::getEnumCases()', ConstantArrayType::class => 'Type::getConstantArrays()', ArrayType::class => 'Type::isArray() or Type::getArrays()', diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index f499aedc28..b53b9d42ae 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -54,6 +54,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getArrays(): array { return []; diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index 1b7d6d12d1..36abedee3d 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -55,6 +55,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index 7c6a1d3a28..e654101f6a 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -56,6 +56,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index 7be53f1143..bc49ea1ad3 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -57,6 +57,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index fe6a361c7b..8056ef72f6 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -55,6 +55,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index 43176d50d7..4a9138f848 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -49,6 +49,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + private function getCanonicalMethodName(): string { return strtolower($this->methodName); diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 1ba0088384..c120411ca1 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -67,6 +67,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index a1f1f0ca2b..3d1a678945 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -66,6 +66,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index 52cac40ed8..f5e6e97a3d 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -46,6 +46,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index 0153c40bf6..50127a2917 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -51,6 +51,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getArrays(): array { return []; diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index f5504b50a9..57d1cfeecd 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -49,6 +49,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getArrays(): array { return []; diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 65f03c5781..ffb7c9efb0 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -77,6 +77,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getArrays(): array { return [$this]; diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 1b008b7034..917a3c5167 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -80,6 +80,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index d3d74e64fe..5ecb4edbcb 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -100,7 +100,12 @@ public function getReferencedClasses(): array public function getObjectClassNames(): array { - return [$this->objectType->getClassName()]; + return $this->objectType->getObjectClassNames(); + } + + public function getObjectClassReflections(): array + { + return $this->objectType->getObjectClassReflections(); } public function accepts(Type $type, bool $strictTypes): TrinaryLogic diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 035b900a9e..e1c14b4e52 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -52,6 +52,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index d5e61eef94..82f3b8c342 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -122,6 +122,18 @@ public function getObjectClassNames(): array return array_values(array_unique($objectClassNames)); } + public function getObjectClassReflections(): array + { + $reflections = []; + foreach ($this->types as $type) { + foreach ($type->getObjectClassReflections() as $reflection) { + $reflections[] = $reflection; + } + } + + return $reflections; + } + public function getArrays(): array { $arrays = []; diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 7b6f753fff..b697674f25 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -66,6 +66,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index 2ed4ccd194..3e83c40e04 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -21,6 +21,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function accepts(Type $type, bool $strictTypes): TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 8e5fbc4db3..becf49fa3d 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -69,6 +69,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getArrays(): array { return []; diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 8075605983..75bdebbb4a 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -62,6 +62,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/NullType.php b/src/Type/NullType.php index 36f87c9484..0686ede4af 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -47,6 +47,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index a959916b4b..f114d466ee 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -236,6 +236,16 @@ public function getObjectClassNames(): array return [$this->className]; } + public function getObjectClassReflections(): array + { + $classReflection = $this->getClassReflection(); + if ($classReflection === null) { + return []; + } + + return [$classReflection]; + } + public function accepts(Type $type, bool $strictTypes): TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index 048fca6a97..72acda465e 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -45,6 +45,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function accepts(Type $type, bool $strictTypes): TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; diff --git a/src/Type/OffsetAccessType.php b/src/Type/OffsetAccessType.php index 0566730539..473f8dc278 100644 --- a/src/Type/OffsetAccessType.php +++ b/src/Type/OffsetAccessType.php @@ -35,6 +35,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array { return array_merge( diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index af1b1c1c23..19157540b5 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -109,6 +109,11 @@ public function getObjectClassNames(): array return $this->getStaticObjectType()->getObjectClassNames(); } + public function getObjectClassReflections(): array + { + return $this->getStaticObjectType()->getObjectClassReflections(); + } + public function getArrays(): array { return $this->getStaticObjectType()->getArrays(); diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index cae793520d..554f9708f5 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -39,6 +39,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function getConstantStrings(): array { return []; diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index edaddd4a3e..05a5db46a6 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -28,6 +28,11 @@ public function getObjectClassNames(): array return $this->resolve()->getObjectClassNames(); } + public function getObjectClassReflections(): array + { + return $this->resolve()->getObjectClassReflections(); + } + public function getArrays(): array { return $this->resolve()->getArrays(); diff --git a/src/Type/Type.php b/src/Type/Type.php index 4eb325e767..16c3f5ac98 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -4,6 +4,7 @@ use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ClassMemberAccessAnswerer; +use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ParametersAcceptor; @@ -30,6 +31,11 @@ public function getReferencedClasses(): array; /** @return list */ public function getObjectClassNames(): array; + /** + * @return list + */ + public function getObjectClassReflections(): array; + /** * Returns object type Foo for class-string and 'Foo' (if Foo is a valid class). */ diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index f153a5e54b..21351dc7a6 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -120,6 +120,11 @@ public function getObjectClassNames(): array return array_values(array_unique($this->pickFromTypes(static fn (Type $type) => $type->getObjectClassNames()))); } + public function getObjectClassReflections(): array + { + return $this->pickFromTypes(static fn (Type $type) => $type->getObjectClassReflections()); + } + public function getArrays(): array { return $this->pickFromTypes(static fn (Type $type) => $type->getArrays()); diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index b57ebb736f..eb24f54ffd 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -48,6 +48,11 @@ public function getObjectClassNames(): array return []; } + public function getObjectClassReflections(): array + { + return []; + } + public function accepts(Type $type, bool $strictTypes): TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; diff --git a/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php index 842bd2a15c..6be9f18d4b 100644 --- a/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php +++ b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php @@ -21,17 +21,17 @@ public function testRule(): void $tipText = 'Learn more: https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated'; $this->analyse([__DIR__ . '/data/instanceof-type.php'], [ [ - 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone and deprecated. Use Type::getObjectClassNames() instead.', + 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone and deprecated. Use Type::getObjectClassNames() or Type::getObjectClassReflections() instead.', 20, $tipText, ], [ - 'Doing instanceof phpstan\type\typewithclassname is error-prone and deprecated. Use Type::getObjectClassNames() instead.', + 'Doing instanceof phpstan\type\typewithclassname is error-prone and deprecated. Use Type::getObjectClassNames() or Type::getObjectClassReflections() instead.', 24, $tipText, ], [ - 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone and deprecated. Use Type::getObjectClassNames() instead.', + 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone and deprecated. Use Type::getObjectClassNames() or Type::getObjectClassReflections() instead.', 36, $tipText, ],