Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Rector\Tests\DowngradePhp82\Rector\Class_\DowngradeStandaloneNullTrueFalseReturnTypeRector\Fixture;

final class NullableTrue
{
public function run(): ?true
{
return rand(0, 1) ? true : null;
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp82\Rector\Class_\DowngradeStandaloneNullTrueFalseReturnTypeRector\Fixture;

final class NullableTrue
{
/**
* @return true|null
*/
public function run(): ?bool
{
return rand(0, 1) ? true : null;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Rector\Tests\DowngradePhp82\Rector\Class_\DowngradeStandaloneNullTrueFalseReturnTypeRector\Fixture;

final class UnionTrue
{
public function run(): null|true
{
return rand(0, 1) ? true : null;
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp82\Rector\Class_\DowngradeStandaloneNullTrueFalseReturnTypeRector\Fixture;

final class UnionTrue
{
/**
* @return null|true
*/
public function run(): null|bool
{
return rand(0, 1) ? true : null;
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
) {
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down
Loading