From 68c3e58e69a7645d3e18f715de4227986f2a5a5e Mon Sep 17 00:00:00 2001 From: Vladimir Zapletal Date: Fri, 4 Aug 2023 10:57:18 +0200 Subject: [PATCH] Enabled more usage variants of MyCLabs\Enum->equals() --- .../Fixture/usage_of_equals.php.inc | 54 ++++++++++++++++++ .../Source/SomeEnum.php | 5 ++ .../MyCLabsMethodCallToEnumConstRector.php | 57 +++++++++++++++++-- 3 files changed, 110 insertions(+), 6 deletions(-) diff --git a/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Fixture/usage_of_equals.php.inc b/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Fixture/usage_of_equals.php.inc index a41be5dc8d9..b7858789b69 100644 --- a/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Fixture/usage_of_equals.php.inc +++ b/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Fixture/usage_of_equals.php.inc @@ -15,6 +15,9 @@ final class UsageOfEquals $compare = SomeEnum::USED_TO_BE_CONST()->equals(SomeEnum::USED_TO_BE_CONST()); $compare = SomeEnum::USED_TO_BE_CONST()->equals($var); $compare = SomeEnum::USED_TO_BE_CONST()->equals($this->prop); + $compare = SomeEnum::USED_TO_BE_CONST()->equals($this->getEnum()); + $compare = SomeEnum::USED_TO_BE_CONST()->equals(self::getStaticEnum()); + $compare = SomeEnum::create()->equals(self::getStaticEnum()); $compare = $var->equals(SomeEnum::USED_TO_BE_CONST()); $compare = $var->equals($var); @@ -23,6 +26,30 @@ final class UsageOfEquals $compare = $this->prop->equals(SomeEnum::USED_TO_BE_CONST()); $compare = $this->prop->equals($var); $compare = $this->prop->equals($this->prop); + + $compare = $this->getEnum()->equals(SomeEnum::USED_TO_BE_CONST()); + $compare = $this->getEnum()->equals($var); + $compare = $this->getEnum()->equals($this->prop); + + $compare = self::getStaticEnum()->equals(SomeEnum::USED_TO_BE_CONST()); + $compare = self::getStaticEnum()->equals($var); + $compare = self::getStaticEnum()->equals($this->prop); + + $compare = $var->equals($this->getEnum()); + $compare = $this->prop->equals($this->getEnum()); + + $compare = $var->equals(self::getStaticEnum()); + $compare = $this->prop->equals(self::getStaticEnum()); + } + + public function getEnum(): SomeEnum + { + return SomeEnum::USED_TO_BE_CONST(); + } + + public static function getStaticEnum(): SomeEnum + { + return SomeEnum::USED_TO_BE_CONST(); } } @@ -45,6 +72,9 @@ final class UsageOfEquals $compare = \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST === \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; $compare = \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST === $var; $compare = \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST === $this->prop; + $compare = \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST === $this->getEnum(); + $compare = \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST === self::getStaticEnum(); + $compare = SomeEnum::create() === self::getStaticEnum(); $compare = $var === \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; $compare = $var === $var; @@ -53,6 +83,30 @@ final class UsageOfEquals $compare = $this->prop === \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; $compare = $this->prop === $var; $compare = $this->prop === $this->prop; + + $compare = $this->getEnum() === \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; + $compare = $this->getEnum() === $var; + $compare = $this->getEnum() === $this->prop; + + $compare = self::getStaticEnum() === \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; + $compare = self::getStaticEnum() === $var; + $compare = self::getStaticEnum() === $this->prop; + + $compare = $var === $this->getEnum(); + $compare = $this->prop === $this->getEnum(); + + $compare = $var === self::getStaticEnum(); + $compare = $this->prop === self::getStaticEnum(); + } + + public function getEnum(): SomeEnum + { + return \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; + } + + public static function getStaticEnum(): SomeEnum + { + return \Rector\Tests\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector\Source\SomeEnum::USED_TO_BE_CONST; } } diff --git a/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Source/SomeEnum.php b/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Source/SomeEnum.php index e522e75f022..e50c25f277c 100644 --- a/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Source/SomeEnum.php +++ b/rules-tests/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector/Source/SomeEnum.php @@ -12,4 +12,9 @@ final class SomeEnum extends Enum { const USED_TO_BE_CONST = 'value'; + + public static function create(): self + { + return SomeEnum::USED_TO_BE_CONST(); + } } diff --git a/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php b/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php index 1aa3470a027..e774d93232f 100644 --- a/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php +++ b/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php @@ -13,6 +13,7 @@ use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; use Rector\Core\Rector\AbstractRector; use Rector\Core\ValueObject\PhpVersionFeature; @@ -33,6 +34,11 @@ final class MyCLabsMethodCallToEnumConstRector extends AbstractRector implements */ private const ENUM_METHODS = ['from', 'values', 'keys', 'isValid', 'search', 'toArray', 'assertValidValue']; + public function __construct( + private readonly ReflectionProvider $reflectionProvider, + ) { + } + public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Refactor MyCLabs enum fetch to Enum const', [ @@ -88,9 +94,20 @@ public function refactor(Node $node): ?Node return null; } + if (! $this->isEnumConstant($className, $enumCaseName)) { + return null; + } + return $this->nodeFactory->createClassConstFetch($className, $enumCaseName); } + private function isEnumConstant(string $className, string $constant) + { + $classReflection = $this->reflectionProvider->getClass($className); + + return $classReflection->hasConstant($constant); + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::ENUM; @@ -148,9 +165,12 @@ private function refactorGetValueMethodCall(MethodCall $methodCall): ?PropertyFe private function refactorEqualsMethodCall(MethodCall $methodCall): ?Identical { - $expr = $this->getValidEnumExpr($methodCall->var); - if (! $expr instanceof Expr) { - return null; + $expr = $this->getNonEnumReturnTypeExpr($methodCall->var); + if ($expr === null) { + $expr = $this->getValidEnumExpr($methodCall->var); + if (! $expr instanceof Expr) { + return null; + } } $arg = $methodCall->getArgs()[0] ?? null; @@ -158,14 +178,39 @@ private function refactorEqualsMethodCall(MethodCall $methodCall): ?Identical return null; } - $right = $this->getValidEnumExpr($arg->value); - if (! $right instanceof Expr) { - return null; + $right = $this->getNonEnumReturnTypeExpr($arg->value); + if ($right === null) { + $right = $this->getValidEnumExpr($arg->value); + if (! $right instanceof Expr) { + return null; + } } return new Identical($expr, $right); } + private function getNonEnumReturnTypeExpr(Node $node): null|ClassConstFetch|Expr + { + if (! $node instanceof StaticCall && ! $node instanceof MethodCall) { + return null; + } + + if ($this->isObjectType($node->class ?? $node->var, new ObjectType('MyCLabs\Enum\Enum'))) { + $methodName = $this->getName($node->name); + if ($methodName === null) { + return null; + } + + $classReflection = $this->reflectionProvider->getClass($this->getName($node->class ?? $node->var)); + // method self::getValidEnumExpr process enum static methods from constants + if ($classReflection->hasConstant($this->getName($node->name))) { + return null; + } + } + + return $node; + } + private function getValidEnumExpr(Node $node): null|ClassConstFetch|Expr { return match ($node::class) {