From 7a23a5a6221db29685eeb5c140d484f14a8bd19d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 May 2026 01:52:30 +0700 Subject: [PATCH 1/4] [DowngradePhp82] Handle nullable true on DowngradeStandaloneNullTrueFalseReturnTypeRector --- .../Fixture/nullable_true.php.inc | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc diff --git a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc new file mode 100644 index 00000000..621f30bf --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc @@ -0,0 +1,30 @@ + +----- + \ No newline at end of file From 4ad398bfb5db8133ae37f15d71b0c4ed6be1a23d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 May 2026 02:11:07 +0700 Subject: [PATCH 2/4] fix --- ...tandaloneNullTrueFalseReturnTypeRector.php | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/rules/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector.php b/rules/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector.php index 007190f2..0d3f7571 100644 --- a/rules/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector.php +++ b/rules/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector.php @@ -17,11 +17,13 @@ use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\NullType; use PHPStan\Type\Type; +use PHPStan\Type\UnionType as PHPStanUnionType; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\PhpParser\AstResolver; use Rector\Rector\AbstractRector; +use Rector\StaticTypeMapper\StaticTypeMapper; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -35,7 +37,8 @@ final class DowngradeStandaloneNullTrueFalseReturnTypeRector extends AbstractRec public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly PhpDocTypeChanger $phpDocTypeChanger, - private readonly AstResolver $astResolver + private readonly AstResolver $astResolver, + private readonly StaticTypeMapper $staticTypeMapper ) { } @@ -83,6 +86,25 @@ public function run(): mixed public function refactor(Node $node): ?Node { $returnType = $node->returnType; + + if ($returnType instanceof NullableType && $returnType->type instanceof Identifier) { + $innerName = $this->getName($returnType->type); + if (in_array($innerName, ['false', 'true'], true)) { + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + $unionType = new PHPStanUnionType([new ConstantBooleanType($innerName === 'true'), new NullType()]); + $this->phpDocTypeChanger->changeReturnType($node, $phpDocInfo, $unionType); + $node->returnType = new NullableType(new Identifier('bool')); + + return $node; + } + + return null; + } + + if ($returnType instanceof UnionType) { + return $this->refactorUnionType($node, $returnType); + } + if (! $returnType instanceof Identifier) { return null; } @@ -102,6 +124,41 @@ public function refactor(Node $node): ?Node return $node; } + /** + * @param ClassMethod|Function_|Closure|ArrowFunction $node + */ + private function refactorUnionType(Node $node, UnionType $unionType): ?Node + { + $hasChanged = false; + + $originalUnionType = clone $unionType; + foreach ($unionType->types as $key => $type) { + if ($type instanceof Identifier) { + $name = $this->getName($type); + if (! in_array($name, ['true', 'false'], true)) { + continue; + } + + $unionType->types[$key] = new Identifier('bool'); + $hasChanged = true; + } + } + + if (! $hasChanged) { + return null; + } + + $unionType->types = array_values(array_unique($unionType->types, SORT_REGULAR)); + $phpStanType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($originalUnionType); + + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + $this->phpDocTypeChanger->changeReturnType($node, $phpDocInfo, $phpStanType); + + $node->returnType = $unionType; + + return $node; + } + private function resolveType(Identifier $identifier): Type { $nodeName = $this->getName($identifier); From c09f9b2a51c8bba8a9deef6b71cbc695a1a497f8 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 May 2026 02:11:10 +0700 Subject: [PATCH 3/4] fix --- .../Fixture/union_true.php.inc | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc diff --git a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc new file mode 100644 index 00000000..f7025a28 --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc @@ -0,0 +1,30 @@ + +----- + \ No newline at end of file From 89488f58e94579beb3c827c507f6cdc27e7995cb Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 21 May 2026 02:11:50 +0700 Subject: [PATCH 4/4] eol --- .../Fixture/nullable_true.php.inc | 2 +- .../Fixture/union_true.php.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc index 621f30bf..4736db3d 100644 --- a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc +++ b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/nullable_true.php.inc @@ -27,4 +27,4 @@ final class NullableTrue } } -?> \ No newline at end of file +?> diff --git a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc index f7025a28..d0df3da1 100644 --- a/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc +++ b/rules-tests/DowngradePhp82/Rector/FunctionLike/DowngradeStandaloneNullTrueFalseReturnTypeRector/Fixture/union_true.php.inc @@ -27,4 +27,4 @@ final class UnionTrue } } -?> \ No newline at end of file +?>