From f5a06553ce4e9b77a9c99c30914461ca42de3f17 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 27 May 2022 00:01:06 +0200 Subject: [PATCH] [CodeQuality] Add InlineIsAInstanceOfRector (#2364) --- config/set/code-quality.php | 43 ++++--- .../Fixture/skip_checked_type_string.php.inc | 13 ++ .../Fixture/skip_string.php.inc | 11 ++ .../Fixture/some_class.php.inc | 31 +++++ .../InlineIsAInstanceOfRectorTest.php | 33 +++++ .../Source/SomeType.php | 9 ++ .../config/configured_rule.php | 10 ++ .../FuncCall/InlineIsAInstanceOfRector.php | 113 ++++++++++++++++++ 8 files changed, 244 insertions(+), 19 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/skip_checked_type_string.php.inc create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/skip_string.php.inc create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/some_class.php.inc create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/InlineIsAInstanceOfRectorTest.php create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Source/SomeType.php create mode 100644 rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/config/configured_rule.php create mode 100644 rules/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector.php diff --git a/config/set/code-quality.php b/config/set/code-quality.php index 081b4bc3c0a..02117ccca71 100644 --- a/config/set/code-quality.php +++ b/config/set/code-quality.php @@ -32,6 +32,7 @@ use Rector\CodeQuality\Rector\FuncCall\ArrayMergeOfNonArraysToSimpleArrayRector; use Rector\CodeQuality\Rector\FuncCall\CallUserFuncWithArrowFunctionToInlineRector; use Rector\CodeQuality\Rector\FuncCall\ChangeArrayPushToArrayAssignRector; use Rector\CodeQuality\Rector\FuncCall\CompactToVariablesRector; +use Rector\CodeQuality\Rector\FuncCall\InlineIsAInstanceOfRector; use Rector\CodeQuality\Rector\FuncCall\IntvalToTypeCastRector; use Rector\CodeQuality\Rector\FuncCall\IsAWithStringWithThirdArgumentRector; use Rector\CodeQuality\Rector\FuncCall\RemoveSoleValueSprintfRector; @@ -162,23 +163,27 @@ return static function (RectorConfig $rectorConfig): void { 'mbstrrpos' => 'mb_strrpos', 'mbsubstr' => 'mb_substr', ]); - $rectorConfig->rule(SetTypeToCastRector::class); - $rectorConfig->rule(LogicalToBooleanRector::class); - $rectorConfig->rule(VarToPublicPropertyRector::class); - $rectorConfig->rule(IssetOnPropertyObjectToPropertyExistsRector::class); - $rectorConfig->rule(NewStaticToNewSelfRector::class); - $rectorConfig->rule(DateTimeToDateTimeInterfaceRector::class); - $rectorConfig->rule(UnwrapSprintfOneArgumentRector::class); - $rectorConfig->rule(SwitchNegatedTernaryRector::class); - $rectorConfig->rule(SingularSwitchToIfRector::class); - $rectorConfig->rule(SimplifyIfNullableReturnRector::class); - $rectorConfig->rule(NarrowUnionTypeDocRector::class); - $rectorConfig->rule(FuncGetArgsToVariadicParamRector::class); - $rectorConfig->rule(CallUserFuncToMethodCallRector::class); - $rectorConfig->rule(CallUserFuncWithArrowFunctionToInlineRector::class); - $rectorConfig->rule(CountArrayToEmptyArrayComparisonRector::class); - $rectorConfig->rule(FlipTypeControlToUseExclusiveTypeRector::class); - $rectorConfig->rule(ExplicitMethodCallOverMagicGetSetRector::class); - $rectorConfig->rule(DoWhileBreakFalseToIfElseRector::class); - $rectorConfig->rule(InlineArrayReturnAssignRector::class); + + $rectorConfig->rules([ + SetTypeToCastRector::class, + LogicalToBooleanRector::class, + VarToPublicPropertyRector::class, + IssetOnPropertyObjectToPropertyExistsRector::class, + NewStaticToNewSelfRector::class, + DateTimeToDateTimeInterfaceRector::class, + UnwrapSprintfOneArgumentRector::class, + SwitchNegatedTernaryRector::class, + SingularSwitchToIfRector::class, + SimplifyIfNullableReturnRector::class, + NarrowUnionTypeDocRector::class, + FuncGetArgsToVariadicParamRector::class, + CallUserFuncToMethodCallRector::class, + CallUserFuncWithArrowFunctionToInlineRector::class, + CountArrayToEmptyArrayComparisonRector::class, + FlipTypeControlToUseExclusiveTypeRector::class, + ExplicitMethodCallOverMagicGetSetRector::class, + DoWhileBreakFalseToIfElseRector::class, + InlineArrayReturnAssignRector::class, + InlineIsAInstanceOfRector::class, + ]); }; diff --git a/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/skip_checked_type_string.php.inc b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/skip_checked_type_string.php.inc new file mode 100644 index 00000000000..f8f7bf8e8b7 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Fixture/skip_checked_type_string.php.inc @@ -0,0 +1,13 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/InlineIsAInstanceOfRectorTest.php b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/InlineIsAInstanceOfRectorTest.php new file mode 100644 index 00000000000..40d5ca7468a --- /dev/null +++ b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/InlineIsAInstanceOfRectorTest.php @@ -0,0 +1,33 @@ +doTestFileInfo($fileInfo); + } + + /** + * @return Iterator + */ + public function provideData(): Iterator + { + return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Source/SomeType.php b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Source/SomeType.php new file mode 100644 index 00000000000..35a55304571 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector/Source/SomeType.php @@ -0,0 +1,9 @@ +rule(InlineIsAInstanceOfRector::class); +}; diff --git a/rules/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector.php b/rules/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector.php new file mode 100644 index 00000000000..3d5c4b05068 --- /dev/null +++ b/rules/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector.php @@ -0,0 +1,113 @@ +> + */ + public function getNodeTypes(): array + { + return [FuncCall::class]; + } + + /** + * @param FuncCall $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->isName($node->name, 'is_a')) { + return null; + } + + $args = $node->getArgs(); + $firstArgValue = $args[0]->value; + + if (! $this->isFirstObjectType($firstArgValue)) { + return null; + } + + $className = $this->resolveClassName($args[1]->value); + if ($className === null) { + return null; + } + + return new Instanceof_($firstArgValue, new FullyQualified($className)); + } + + private function resolveClassName(Expr $expr): ?string + { + if (! $expr instanceof ClassConstFetch) { + return null; + } + + $type = $this->getType($expr); + + if ($type instanceof GenericClassStringType) { + $type = $type->getGenericType(); + } + + if (! $type instanceof TypeWithClassName) { + return null; + } + + return $type->getClassName(); + } + + private function isFirstObjectType(Expr $expr): bool + { + $exprType = $this->getType($expr); + if ($exprType instanceof ObjectWithoutClassType) { + return true; + } + + return $exprType instanceof ObjectType; + } +}