From 6e419da671981031688d2231512c84111439345c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 9 Oct 2025 23:29:25 +0700 Subject: [PATCH 1/2] [TypeDeclarationDocblocks] Fix missing backslash on class-string type on DocblockGetterReturnArrayFromPropertyDocblockVarRector --- .../Fixture/add_prefix_backslash.php.inc | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc new file mode 100644 index 00000000000..76a5ed639c9 --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockGetterReturnArrayFromPropertyDocblockVarRector/Fixture/add_prefix_backslash.php.inc @@ -0,0 +1,54 @@ +>> */ + protected array $duplicateNames, + ) { + parent::__construct( + 'Some solutions have duplicate names.', + ); + } + + public function getDuplicateNames(): array + { + return $this->duplicateNames; + } +} + +?> +----- +>> */ + protected array $duplicateNames, + ) { + parent::__construct( + 'Some solutions have duplicate names.', + ); + } + + /** + * @return array[]> + */ + public function getDuplicateNames(): array + { + return $this->duplicateNames; + } +} + +?> From 11c6bc6858750c15f4ef879e443b34aeff76cae6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 9 Oct 2025 23:37:45 +0700 Subject: [PATCH 2/2] fix --- .../Fixture/class_string_case_sensitive.php.inc | 2 +- .../Fixture/phpdocs.php.inc | 4 ++-- .../TypeMapper/ClassStringTypeMapper.php | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Class_/CompleteDynamicPropertiesRector/Fixture/class_string_case_sensitive.php.inc b/rules-tests/CodeQuality/Rector/Class_/CompleteDynamicPropertiesRector/Fixture/class_string_case_sensitive.php.inc index de896c8132b..29ba6a5af3b 100644 --- a/rules-tests/CodeQuality/Rector/Class_/CompleteDynamicPropertiesRector/Fixture/class_string_case_sensitive.php.inc +++ b/rules-tests/CodeQuality/Rector/Class_/CompleteDynamicPropertiesRector/Fixture/class_string_case_sensitive.php.inc @@ -17,7 +17,7 @@ class ClassStringCaseSensitive class ClassStringCaseSensitive { /** - * @var class-string + * @var class-string<\ClassStringCaseSensitive> */ public $value; public function set() diff --git a/rules-tests/DeadCode/Rector/FunctionLike/NarrowTooWideReturnTypeRector/Fixture/phpdocs.php.inc b/rules-tests/DeadCode/Rector/FunctionLike/NarrowTooWideReturnTypeRector/Fixture/phpdocs.php.inc index 40d92c06dd3..9099aeb6698 100644 --- a/rules-tests/DeadCode/Rector/FunctionLike/NarrowTooWideReturnTypeRector/Fixture/phpdocs.php.inc +++ b/rules-tests/DeadCode/Rector/FunctionLike/NarrowTooWideReturnTypeRector/Fixture/phpdocs.php.inc @@ -83,14 +83,14 @@ final class PhpDocs /** * @param class-string $class - * @return class-string + * @return class-string<\Rector\Tests\DeadCode\Rector\FunctionLike\NarrowTooWideReturnTypeRector\Source\SomeInterface> */ public function bar(string $class): string { return $class; } - /** @return class-string */ + /** @return class-string<\Rector\Tests\DeadCode\Rector\FunctionLike\NarrowTooWideReturnTypeRector\Source\SomeInterface> */ public function baz(string $class): string { return SomeInterface::class; diff --git a/src/PHPStanStaticTypeMapper/TypeMapper/ClassStringTypeMapper.php b/src/PHPStanStaticTypeMapper/TypeMapper/ClassStringTypeMapper.php index 623ac047ea2..2249fbe94e0 100644 --- a/src/PHPStanStaticTypeMapper/TypeMapper/ClassStringTypeMapper.php +++ b/src/PHPStanStaticTypeMapper/TypeMapper/ClassStringTypeMapper.php @@ -8,7 +8,9 @@ use PhpParser\Node\Identifier; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\ClassStringType; +use PHPStan\Type\ObjectType; use PHPStan\Type\Type; +use PHPStan\Type\TypeTraverser; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\ValueObject\PhpVersionFeature; @@ -33,6 +35,20 @@ public function getNodeClass(): string */ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { + $type = TypeTraverser::map($type, static function (Type $type, callable $traverse): Type { + if (! $type instanceof ObjectType) { + return $traverse($type); + } + + $typeClass = $type::class; + + if ($typeClass === 'PHPStan\Type\ObjectType') { + return new ObjectType('\\' . $type->getClassName()); + } + + return $traverse($type); + }); + return $type->toPhpDocNode(); }