mirror of
https://github.com/rectorphp/rector.git
synced 2024-07-05 00:53:31 +00:00
add UnionTypesRector
This commit is contained in:
parent
a9cd107fb9
commit
b930046917
|
@ -100,7 +100,8 @@
|
||||||
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src",
|
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src",
|
||||||
"Rector\\StrictCodeQuality\\": "packages/StrictCodeQuality/src",
|
"Rector\\StrictCodeQuality\\": "packages/StrictCodeQuality/src",
|
||||||
"Rector\\DynamicTypeAnalysis\\": "packages/DynamicTypeAnalysis/src",
|
"Rector\\DynamicTypeAnalysis\\": "packages/DynamicTypeAnalysis/src",
|
||||||
"Rector\\PhpDeglobalize\\": "packages/PhpDeglobalize/src"
|
"Rector\\PhpDeglobalize\\": "packages/PhpDeglobalize/src",
|
||||||
|
"Rector\\Php80\\": "packages/Php80/src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
|
@ -157,7 +158,8 @@
|
||||||
"Rector\\ZendToSymfony\\Tests\\": "packages/ZendToSymfony/tests",
|
"Rector\\ZendToSymfony\\Tests\\": "packages/ZendToSymfony/tests",
|
||||||
"Rector\\StrictCodeQuality\\Tests\\": "packages/StrictCodeQuality/tests",
|
"Rector\\StrictCodeQuality\\Tests\\": "packages/StrictCodeQuality/tests",
|
||||||
"Rector\\DynamicTypeAnalysis\\Tests\\": "packages/DynamicTypeAnalysis/tests",
|
"Rector\\DynamicTypeAnalysis\\Tests\\": "packages/DynamicTypeAnalysis/tests",
|
||||||
"Rector\\PhpDeglobalize\\Tests\\": "packages/PhpDeglobalize/tests"
|
"Rector\\PhpDeglobalize\\Tests\\": "packages/PhpDeglobalize/tests",
|
||||||
|
"Rector\\Php80\\Tests\\": "packages/Php80/tests"
|
||||||
},
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"packages/Symfony/tests/Rector/FrameworkBundle/AbstractToConstructorInjectionRectorSource",
|
"packages/Symfony/tests/Rector/FrameworkBundle/AbstractToConstructorInjectionRectorSource",
|
||||||
|
|
131
packages/Php80/src/Rector/FunctionLike/UnionTypesRector.php
Normal file
131
packages/Php80/src/Rector/FunctionLike/UnionTypesRector.php
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Php80\Rector\FunctionLike;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr\ArrowFunction;
|
||||||
|
use PhpParser\Node\FunctionLike;
|
||||||
|
use PhpParser\Node\Stmt\ClassMethod;
|
||||||
|
use PhpParser\Node\Stmt\Function_;
|
||||||
|
use PhpParser\Node\UnionType as PhpParserUnionType;
|
||||||
|
use PHPStan\Type\UnionType;
|
||||||
|
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||||
|
use Rector\Rector\AbstractRector;
|
||||||
|
use Rector\RectorDefinition\CodeSample;
|
||||||
|
use Rector\RectorDefinition\RectorDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \Rector\Php80\Tests\Rector\FunctionLike\UnionTypesRector\UnionTypesRectorTest
|
||||||
|
*/
|
||||||
|
final class UnionTypesRector extends AbstractRector
|
||||||
|
{
|
||||||
|
public function getDefinition(): RectorDefinition
|
||||||
|
{
|
||||||
|
return new RectorDefinition(
|
||||||
|
'Change docs types to union types, where possible (properties are covered by TypedPropertiesRector)',
|
||||||
|
[
|
||||||
|
new CodeSample(
|
||||||
|
<<<'PHP'
|
||||||
|
class SomeClass {
|
||||||
|
/**
|
||||||
|
* @param array|int $number
|
||||||
|
* @return bool|float
|
||||||
|
*/
|
||||||
|
public function go($number)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PHP
|
||||||
|
,
|
||||||
|
<<<'PHP'
|
||||||
|
class SomeClass {
|
||||||
|
/**
|
||||||
|
* @param array|int $number
|
||||||
|
* @return bool|float
|
||||||
|
*/
|
||||||
|
public function go(array|int $number): bool|float
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PHP
|
||||||
|
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getNodeTypes(): array
|
||||||
|
{
|
||||||
|
return [FunctionLike::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassMethod|Function_|Node\Expr\Closure|ArrowFunction $node
|
||||||
|
*/
|
||||||
|
public function refactor(Node $node): ?Node
|
||||||
|
{
|
||||||
|
$phpDocInfo = $this->getPhpDocInfo($node);
|
||||||
|
if ($phpDocInfo === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->refactorParamTypes($node, $phpDocInfo);
|
||||||
|
$this->refactorReturnType($node, $phpDocInfo);
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassMethod|Function_|Node\Expr\Closure|ArrowFunction $functionLike
|
||||||
|
*/
|
||||||
|
private function refactorReturnType(FunctionLike $functionLike, PhpDocInfo $phpDocInfo): void
|
||||||
|
{
|
||||||
|
// do not override existing return type
|
||||||
|
if ($functionLike->getReturnType() !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnType = $phpDocInfo->getReturnType();
|
||||||
|
if (! $returnType instanceof UnionType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$phpParserUnionType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($returnType);
|
||||||
|
if (! $phpParserUnionType instanceof PhpParserUnionType) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$functionLike->returnType = $phpParserUnionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassMethod|Function_|Node\Expr\Closure|ArrowFunction $functionLike
|
||||||
|
*/
|
||||||
|
private function refactorParamTypes(FunctionLike $functionLike, PhpDocInfo $phpDocInfo): void
|
||||||
|
{
|
||||||
|
foreach ($functionLike->params as $param) {
|
||||||
|
if ($param->type !== null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var string $paramName */
|
||||||
|
$paramName = $this->getName($param->var);
|
||||||
|
$paramType = $phpDocInfo->getParamType($paramName);
|
||||||
|
if (! $paramType instanceof UnionType) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$phpParserUnionType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($paramType);
|
||||||
|
if (! $phpParserUnionType instanceof PhpParserUnionType) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$param->type = $phpParserUnionType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rector\Php80\Tests\Rector\FunctionLike\UnionTypesRector\Fixture;
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
/**
|
||||||
|
* @param array|int $number
|
||||||
|
* @return bool|float
|
||||||
|
*/
|
||||||
|
public function go($number)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
-----
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rector\Php80\Tests\Rector\FunctionLike\UnionTypesRector\Fixture;
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
/**
|
||||||
|
* @param array|int $number
|
||||||
|
* @return bool|float
|
||||||
|
*/
|
||||||
|
public function go(array|int $number): bool|float
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Php80\Tests\Rector\FunctionLike\UnionTypesRector;
|
||||||
|
|
||||||
|
use Iterator;
|
||||||
|
use Rector\Php80\Rector\FunctionLike\UnionTypesRector;
|
||||||
|
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||||
|
|
||||||
|
final class UnionTypesRectorTest extends AbstractRectorTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider provideDataForTest()
|
||||||
|
*/
|
||||||
|
public function test(string $file): void
|
||||||
|
{
|
||||||
|
$this->doTestFile($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideDataForTest(): Iterator
|
||||||
|
{
|
||||||
|
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRectorClass(): string
|
||||||
|
{
|
||||||
|
return UnionTypesRector::class;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ namespace Rector\Utils\RectorGenerator\Configuration;
|
||||||
use Nette\Utils\Strings;
|
use Nette\Utils\Strings;
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use Rector\Exception\FileSystem\FileNotFoundException;
|
use Rector\Exception\FileSystem\FileNotFoundException;
|
||||||
|
use Rector\Exception\ShouldNotHappenException;
|
||||||
use Rector\Set\Set;
|
use Rector\Set\Set;
|
||||||
use Rector\Utils\RectorGenerator\Exception\ConfigurationException;
|
use Rector\Utils\RectorGenerator\Exception\ConfigurationException;
|
||||||
use Rector\Utils\RectorGenerator\Node\NodeClassProvider;
|
use Rector\Utils\RectorGenerator\Node\NodeClassProvider;
|
||||||
|
@ -114,6 +115,8 @@ final class ConfigurationFactory
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new ShouldNotHappenException(sprintf('Node endings with "%s" was not found', $nodeType));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_unique($fqnNodeTypes);
|
return array_unique($fqnNodeTypes);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user