mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-13 14:42:23 +00:00
[PHP 8.0] Add property support to ConstantListClassToEnumRector (#2422)
* add property enum support * fixup! add property enum support
This commit is contained in:
parent
7722a57d80
commit
0df2351b89
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Php80\Rector\Class_\ConstantListClassToEnumRector\Fixture;
|
||||
|
||||
use Rector\Tests\Php80\Rector\Class_\ConstantListClassToEnumRector\Source\Gear;
|
||||
|
||||
final class EnumTypeProperty
|
||||
{
|
||||
/**
|
||||
* @var Gear::* $gear
|
||||
*/
|
||||
private $gear;
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Php80\Rector\Class_\ConstantListClassToEnumRector\Fixture;
|
||||
|
||||
use Rector\Tests\Php80\Rector\Class_\ConstantListClassToEnumRector\Source\Gear;
|
||||
|
||||
final class EnumTypeProperty
|
||||
{
|
||||
private \Rector\Tests\Php80\Rector\Class_\ConstantListClassToEnumRector\Source\Gear $gear;
|
||||
}
|
||||
|
||||
?>
|
|
@ -7,12 +7,14 @@ namespace Rector\Php80\NodeAnalyzer;
|
|||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\Reflection\ParameterReflection;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Rector\Php80\ValueObject\ClassNameAndTagValueNode;
|
||||
|
||||
/**
|
||||
* Detects enum-like params, e.g.
|
||||
|
@ -25,8 +27,10 @@ final class EnumParamAnalyzer
|
|||
) {
|
||||
}
|
||||
|
||||
public function matchParameterClassName(ParameterReflection $parameterReflection, PhpDocInfo $phpDocInfo): ?string
|
||||
{
|
||||
public function matchParameterClassName(
|
||||
ParameterReflection $parameterReflection,
|
||||
PhpDocInfo $phpDocInfo
|
||||
): ?ClassNameAndTagValueNode {
|
||||
$paramTagValueNode = $phpDocInfo->getParamTagValueByName($parameterReflection->getName());
|
||||
if (! $paramTagValueNode instanceof ParamTagValueNode) {
|
||||
return null;
|
||||
|
@ -41,17 +45,37 @@ final class EnumParamAnalyzer
|
|||
return null;
|
||||
}
|
||||
|
||||
return $className;
|
||||
return new ClassNameAndTagValueNode($className, $paramTagValueNode);
|
||||
}
|
||||
|
||||
public function matchReturnClassName(PhpDocInfo $phpDocInfo): ?string
|
||||
public function matchReturnClassName(PhpDocInfo $phpDocInfo): ?ClassNameAndTagValueNode
|
||||
{
|
||||
$returnTagValueNode = $phpDocInfo->getReturnTagValue();
|
||||
if (! $returnTagValueNode instanceof ReturnTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->resolveClassFromConstType($returnTagValueNode->type);
|
||||
$className = $this->resolveClassFromConstType($returnTagValueNode->type);
|
||||
if (! is_string($className)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ClassNameAndTagValueNode($className, $returnTagValueNode);
|
||||
}
|
||||
|
||||
public function matchPropertyClassName(PhpDocInfo $phpDocInfo): ?ClassNameAndTagValueNode
|
||||
{
|
||||
$varTagValueNode = $phpDocInfo->getVarTagValueNode();
|
||||
if (! $varTagValueNode instanceof VarTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$className = $this->resolveClassFromConstType($varTagValueNode->type);
|
||||
if (! is_string($className)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ClassNameAndTagValueNode($className, $varTagValueNode);
|
||||
}
|
||||
|
||||
private function resolveClassFromConstType(TypeNode $typeNode): ?string
|
||||
|
|
|
@ -9,8 +9,7 @@ use PhpParser\Node\Name\FullyQualified;
|
|||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
use PHPStan\Reflection\ParametersAcceptorSelector;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
|
@ -19,6 +18,7 @@ use Rector\Core\Rector\AbstractRector;
|
|||
use Rector\Core\Reflection\ReflectionResolver;
|
||||
use Rector\Php80\NodeAnalyzer\EnumConstListClassDetector;
|
||||
use Rector\Php80\NodeAnalyzer\EnumParamAnalyzer;
|
||||
use Rector\Php80\ValueObject\ClassNameAndTagValueNode;
|
||||
use Rector\Php81\NodeFactory\EnumFactory;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
@ -68,11 +68,11 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class, ClassMethod::class];
|
||||
return [Class_::class, ClassMethod::class, Property::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_|ClassMethod $node
|
||||
* @param Class_|ClassMethod|Property $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
|
@ -84,7 +84,11 @@ CODE_SAMPLE
|
|||
return $this->enumFactory->createFromClass($node);
|
||||
}
|
||||
|
||||
return $this->refactorClassMethod($node);
|
||||
if ($node instanceof ClassMethod) {
|
||||
return $this->refactorClassMethod($node);
|
||||
}
|
||||
|
||||
return $this->refactorProperty($node);
|
||||
}
|
||||
|
||||
private function refactorClassMethod(ClassMethod $classMethod): ?ClassMethod
|
||||
|
@ -137,8 +141,11 @@ CODE_SAMPLE
|
|||
|
||||
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
|
||||
foreach ($parametersAcceptor->getParameters() as $parameterReflection) {
|
||||
$enumLikeClass = $this->enumParamAnalyzer->matchParameterClassName($parameterReflection, $phpDocInfo);
|
||||
if ($enumLikeClass === null) {
|
||||
$classNameAndTagValueNode = $this->enumParamAnalyzer->matchParameterClassName(
|
||||
$parameterReflection,
|
||||
$phpDocInfo
|
||||
);
|
||||
if (! $classNameAndTagValueNode instanceof ClassNameAndTagValueNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -148,12 +155,10 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
// change and remove
|
||||
$param->type = new FullyQualified($enumLikeClass);
|
||||
$param->type = new FullyQualified($classNameAndTagValueNode->getEnumClass());
|
||||
$hasNodeChanged = true;
|
||||
|
||||
/** @var ParamTagValueNode $paramTagValueNode */
|
||||
$paramTagValueNode = $phpDocInfo->getParamTagValueByName($parameterReflection->getName());
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $paramTagValueNode);
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $classNameAndTagValueNode->getTagValueNode());
|
||||
}
|
||||
|
||||
return $hasNodeChanged;
|
||||
|
@ -161,17 +166,34 @@ CODE_SAMPLE
|
|||
|
||||
private function refactorReturn(PhpDocInfo $phpDocInfo, ClassMethod $classMethod): bool
|
||||
{
|
||||
$returnType = $this->enumParamAnalyzer->matchReturnClassName($phpDocInfo);
|
||||
if ($returnType === null) {
|
||||
$classNameAndTagValueNode = $this->enumParamAnalyzer->matchReturnClassName($phpDocInfo);
|
||||
if (! $classNameAndTagValueNode instanceof ClassNameAndTagValueNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$classMethod->returnType = new FullyQualified($returnType);
|
||||
$classMethod->returnType = new FullyQualified($classNameAndTagValueNode->getEnumClass());
|
||||
|
||||
/** @var ReturnTagValueNode $returnTagValueNode */
|
||||
$returnTagValueNode = $phpDocInfo->getReturnTagValue();
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $returnTagValueNode);
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $classNameAndTagValueNode->getTagValueNode());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function refactorProperty(Property $property): ?Property
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
|
||||
if (! $phpDocInfo instanceof PhpDocInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classNameAndTagValueNode = $this->enumParamAnalyzer->matchPropertyClassName($phpDocInfo);
|
||||
if (! $classNameAndTagValueNode instanceof ClassNameAndTagValueNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$property->type = new FullyQualified($classNameAndTagValueNode->getEnumClass());
|
||||
|
||||
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $classNameAndTagValueNode->getTagValueNode());
|
||||
|
||||
return $property;
|
||||
}
|
||||
}
|
||||
|
|
28
rules/Php80/ValueObject/ClassNameAndTagValueNode.php
Normal file
28
rules/Php80/ValueObject/ClassNameAndTagValueNode.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php80\ValueObject;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
|
||||
final class ClassNameAndTagValueNode
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $enumClass,
|
||||
private readonly ParamTagValueNode|ReturnTagValueNode|VarTagValueNode $tagValueNode
|
||||
) {
|
||||
}
|
||||
|
||||
public function getEnumClass(): string
|
||||
{
|
||||
return $this->enumClass;
|
||||
}
|
||||
|
||||
public function getTagValueNode(): ParamTagValueNode|ReturnTagValueNode|VarTagValueNode
|
||||
{
|
||||
return $this->tagValueNode;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user