From d3f69305b957aa2e5aed4bfd955f8e3ad17003e4 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 15 Sep 2025 21:17:12 +0700 Subject: [PATCH 1/2] [TypeDeclarationDocblocks] Strip never[] on docblock @ return on DocblockReturnArrayFromDirectArrayInstanceRector --- .../Fixture/strip_empty_combine.php.inc | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc new file mode 100644 index 00000000000..03413f6ccd1 --- /dev/null +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc @@ -0,0 +1,78 @@ + false, + 'b' => 'b', + 'c' => true, + 'd' => $this->getNullable(), + 'class' => StripEmptyCombine::class, + 'opt' => [], + 'init' => false, + 'attrs' => [ + 'x' => 'x', + 'class' => 'pick', + 'apply' => 'true', + 'head' => $this->trans('foo'), + ], + ]; + } + + private function getNullable(): ?string + { + return null; + } + + function trans(): string + { + return 'foo'; + } +} + +?> +----- +|null> + */ + public function get(): array + { + return [ + 'a' => false, + 'b' => 'b', + 'c' => true, + 'd' => $this->getNullable(), + 'class' => StripEmptyCombine::class, + 'opt' => [], + 'init' => false, + 'attrs' => [ + 'x' => 'x', + 'class' => 'pick', + 'apply' => 'true', + 'head' => $this->trans('foo'), + ], + ]; + } + + private function getNullable(): ?string + { + return null; + } + + function trans(): string + { + return 'foo'; + } +} + +?> From f9e5090c00e3c07766e6b1c0269e1adc0bf416df Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 15 Sep 2025 21:47:24 +0700 Subject: [PATCH 2/2] use mixed[] --- .../Fixture/strip_empty_combine.php.inc | 2 +- src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc index 03413f6ccd1..99b4b5c8fc4 100644 --- a/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc +++ b/rules-tests/TypeDeclarationDocblocks/Rector/ClassMethod/DocblockReturnArrayFromDirectArrayInstanceRector/Fixture/strip_empty_combine.php.inc @@ -43,7 +43,7 @@ namespace Rector\Tests\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockRetur final class StripEmptyCombine { /** - * @return array|null> + * @return array|null> */ public function get(): array { diff --git a/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php b/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php index 339745d66ef..e900d9e01eb 100644 --- a/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php +++ b/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php @@ -13,6 +13,9 @@ use PhpParser\Node\NullableType; use PhpParser\Node\UnionType as PhpParserUnionType; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Type\ArrayType; +use PHPStan\Type\MixedType; +use PHPStan\Type\NeverType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode; @@ -55,6 +58,10 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { $unionTypesNodes = []; foreach ($type->getTypes() as $unionedType) { + if ($unionedType instanceof ArrayType && $unionedType->getItemType() instanceof NeverType) { + $unionedType = new ArrayType($unionedType->getKeyType(), new MixedType()); + } + $unionTypesNodes[] = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($unionedType); }