diff --git a/stubs/Php80.phpstub b/stubs/Php80.phpstub index 5d3c9fcf4..e26dffef4 100644 --- a/stubs/Php80.phpstub +++ b/stubs/Php80.phpstub @@ -89,15 +89,17 @@ class ReflectionClass implements Reflector { public function getDocComment(): string|false {} /** - * @param ReflectionClass|class-string $class - * + * @template J as object + * @param self|class-string $class + * @psalm-assert-if-true self $this * @psalm-pure */ public function isSubclassOf(self|string $class): bool {} /** - * @param self|class-string $interface - * + * @template J as object + * @param self|interface-string $interface + * @psalm-assert-if-true self $this * @psalm-pure */ public function implementsInterface(self|string $interface): bool {} diff --git a/stubs/Reflection.phpstub b/stubs/Reflection.phpstub index 02bfa3859..9264e58dc 100644 --- a/stubs/Reflection.phpstub +++ b/stubs/Reflection.phpstub @@ -147,15 +147,13 @@ class ReflectionClass implements Reflector { public function getReflectionConstants(?int $filter = null): array {} /** - * @return array - * + * @return array * @psalm-pure */ public function getInterfaces(): array {} /** - * @return list - * + * @return list * @psalm-pure */ public function getInterfaceNames(): array {} @@ -192,7 +190,12 @@ class ReflectionClass implements Reflector { */ public function getModifiers(): bool {} - /** @psalm-pure */ + /** + * @template J as object + * @param J $object + * @psalm-assert-if-true T&J $object + * @psalm-pure + */ public function isInstance(object $object): bool {} /** @@ -222,8 +225,9 @@ class ReflectionClass implements Reflector { public function getParentClass() {} /** - * @param ReflectionClass|class-string $class - * + * @template J as object + * @param self|class-string $class + * @psalm-assert-if-true self $this * @psalm-pure */ public function isSubclassOf($class): bool {} @@ -245,8 +249,9 @@ class ReflectionClass implements Reflector { public function isIterable(): bool {} /** - * @param self|class-string $interface - * + * @template J as object + * @param self|interface-string $interface + * @psalm-assert-if-true self $this * @psalm-pure */ public function implementsInterface($interface): bool {} @@ -275,7 +280,7 @@ class ReflectionClass implements Reflector { public function getShortName(): string {} /** - * @return ?array + * @return ?list * @psalm-ignore-nullable-return * @psalm-pure */ diff --git a/tests/ReflectionTest.php b/tests/ReflectionTest.php new file mode 100644 index 000000000..fb6e54cb3 --- /dev/null +++ b/tests/ReflectionTest.php @@ -0,0 +1,47 @@ + [ + 'code' => <<<'PHP' + isSubclassOf(Iterator::class)) { + throw new Exception(); + } + PHP, + 'assertions' => ['$a===' => 'ReflectionClass'], + ]; + yield 'ReflectionClass::implementsInterface' => [ + 'code' => <<<'PHP' + implementsInterface(Iterator::class)) { + throw new Exception(); + } + PHP, + 'assertions' => ['$a===' => 'ReflectionClass'], + ]; + yield 'ReflectionClass::isInstance' => [ + 'code' => <<<'PHP' + isInstance($a)) { + throw new Exception(); + } + PHP, + 'assertions' => ['$a===' => 'Iterator&stdClass'], + ]; + } +} diff --git a/tests/Traits/ValidCodeAnalysisTestTrait.php b/tests/Traits/ValidCodeAnalysisTestTrait.php index f5f710ecb..ea9e70a46 100644 --- a/tests/Traits/ValidCodeAnalysisTestTrait.php +++ b/tests/Traits/ValidCodeAnalysisTestTrait.php @@ -18,7 +18,15 @@ use const PHP_VERSION; trait ValidCodeAnalysisTestTrait { /** - * @return iterable,ignored_issues?:list,php_version?:string}> + * @return iterable< + * string, + * array{ + * code: string, + * assertions?: array, + * ignored_issues?: list, + * php_version?: string, + * } + * > */ abstract public function providerValidCodeParse(): iterable;