From cdf9cb50129502217aca5a3d9ee3ed0c3795a148 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 30 Jul 2021 11:18:09 +0200 Subject: [PATCH] Scalar type in PHPDoc can mean an existing class --- src/PhpDoc/TypeNodeResolver.php | 6 +++ .../Rules/Generics/ClassAncestorsRuleTest.php | 5 ++ .../Rules/Generics/data/scalar-class-name.php | 49 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 tests/PHPStan/Rules/Generics/data/scalar-class-name.php diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index 37298c94ee..68bc957b54 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -156,6 +156,12 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco return new BenevolentUnionType([new IntegerType(), new StringType()]); case 'scalar': + $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); + + if ($type !== null) { + return $type; + } + return new UnionType([new IntegerType(), new FloatType(), new StringType(), new BooleanType()]); case 'number': diff --git a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php index ee5db5befc..3a121c2fe8 100644 --- a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php @@ -216,4 +216,9 @@ public function testCrossCheckInterfaces(): void ]); } + public function testScalarClassName(): void + { + $this->analyse([__DIR__ . '/data/scalar-class-name.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Generics/data/scalar-class-name.php b/tests/PHPStan/Rules/Generics/data/scalar-class-name.php new file mode 100644 index 0000000000..dc194c1da5 --- /dev/null +++ b/tests/PHPStan/Rules/Generics/data/scalar-class-name.php @@ -0,0 +1,49 @@ + + */ +class The implements Scalar +{ + /** + * @param T $subject + * @param Closure(T): mixed $context + */ + public function __construct( + /** + * @var T + */ + private mixed $subject, + /** + * @var Closure(T): mixed + */ + private Closure $context + ) { + } + /** + * @return T + */ + public function value(): mixed + { + ($this->context)($this->subject); + return $this->subject; + } +}