From bcc5055d48dc129eaaa6d2f1dc7e967f15c7f2cd Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 27 May 2020 00:22:22 +0200 Subject: [PATCH] [Privatization] Add PrivatizeFinalClassMethodRector --- config/set/privatization/privatization.yaml | 1 + .../PrivatizeFinalClassMethodRector.php | 123 ++++++++++++++++++ .../change_parent_without_care.php.inc | 29 +++++ .../Fixture/fixture.php.inc | 25 ++++ .../Fixture/keep_create_component.php.inc | 10 ++ .../keep_parent_protected_method.php.inc | 12 ++ .../PrivatizeFinalClassMethodRectorTest.php | 30 +++++ .../AbstractClassWithProtectedClassMethod.php | 12 ++ .../change_parent_without_care.php.inc | 4 +- .../Fixture/keep_parent_protected.php.inc | 2 +- .../AbstractClassWithProtectedProperty.php | 2 +- 11 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 rules/privatization/src/Rector/ClassMethod/PrivatizeFinalClassMethodRector.php create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/change_parent_without_care.php.inc create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/fixture.php.inc create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/keep_create_component.php.inc create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/keep_parent_protected_method.php.inc create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/PrivatizeFinalClassMethodRectorTest.php create mode 100644 rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Source/AbstractClassWithProtectedClassMethod.php rename rules/privatization/tests/Rector/Property/PrivatizeFinalClassPropertyRector/{ => Source}/AbstractClassWithProtectedProperty.php (87%) diff --git a/config/set/privatization/privatization.yaml b/config/set/privatization/privatization.yaml index 810d032e6132..79ad2da098fe 100644 --- a/config/set/privatization/privatization.yaml +++ b/config/set/privatization/privatization.yaml @@ -4,3 +4,4 @@ services: Rector\Privatization\Rector\Property\PrivatizeLocalPropertyToPrivatePropertyRector: null Rector\Privatization\Rector\ClassConst\PrivatizeLocalClassConstantRector: null Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector: null + Rector\Privatization\Rector\ClassMethod\PrivatizeFinalClassMethodRector: null diff --git a/rules/privatization/src/Rector/ClassMethod/PrivatizeFinalClassMethodRector.php b/rules/privatization/src/Rector/ClassMethod/PrivatizeFinalClassMethodRector.php new file mode 100644 index 000000000000..26fb950e8787 --- /dev/null +++ b/rules/privatization/src/Rector/ClassMethod/PrivatizeFinalClassMethodRector.php @@ -0,0 +1,123 @@ +getAttribute(AttributeKey::CLASS_NODE); + if (! $class instanceof Class_) { + return null; + } + + if (! $class->isFinal()) { + return null; + } + + if ($this->shouldSkipClassMethod($node)) { + return null; + } + + if ($class->extends === null) { + $this->makePrivate($node); + return $node; + } + + if ($this->isClassMethodVisibilityGuardedByParent($node, $class)) { + return null; + } + + $this->makePrivate($node); + + return $node; + } + + private function shouldSkipClassMethod(ClassMethod $classMethod): bool + { + if ($this->isName($classMethod, 'createComponent*')) { + return true; + } + + return ! $classMethod->isProtected(); + } + + private function isClassMethodVisibilityGuardedByParent(ClassMethod $classMethod, Class_ $class): bool + { + if ($class->extends === null) { + return false; + } + + $parentClasses = $this->getParentClasses($class); + $propertyName = $this->getName($classMethod); + + foreach ($parentClasses as $parentClass) { + if (method_exists($parentClass, $propertyName)) { + return true; + } + } + + return false; + } + + /** + * @return string[] + */ + private function getParentClasses(Class_ $class): array + { + /** @var string $className */ + $className = $this->getName($class); + + return class_parents($className); + } +} diff --git a/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/change_parent_without_care.php.inc b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/change_parent_without_care.php.inc new file mode 100644 index 000000000000..257a2c04d35f --- /dev/null +++ b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/change_parent_without_care.php.inc @@ -0,0 +1,29 @@ + +----- + diff --git a/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/fixture.php.inc b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/fixture.php.inc new file mode 100644 index 000000000000..aceed24af59a --- /dev/null +++ b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/fixture.php.inc @@ -0,0 +1,25 @@ + +----- + diff --git a/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/keep_create_component.php.inc b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/keep_create_component.php.inc new file mode 100644 index 000000000000..45209f8c3431 --- /dev/null +++ b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Fixture/keep_create_component.php.inc @@ -0,0 +1,10 @@ +doTestFile($file); + } + + public function provideData(): Iterator + { + return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + protected function getRectorClass(): string + { + return PrivatizeFinalClassMethodRector::class; + } +} diff --git a/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Source/AbstractClassWithProtectedClassMethod.php b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Source/AbstractClassWithProtectedClassMethod.php new file mode 100644 index 000000000000..c6e013fe815f --- /dev/null +++ b/rules/privatization/tests/Rector/ClassMethod/PrivatizeFinalClassMethodRector/Source/AbstractClassWithProtectedClassMethod.php @@ -0,0 +1,12 @@ +