diff --git a/CHANGELOG.md b/CHANGELOG.md index ccfaaa7a..fae4f281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ For a full diff see [`2.5.0...main`][2.5.0...main]. - Adjusted `Methods\FinalInAbstractClassRule` to ignore Doctrine embeddables and entities ([#396]), by [@localheinz] - Adjusted `Expressions\NoCompactRule` to detect usages of `compact()` with incorrect case ([#889]), by [@localheinz] - Adjusted `Methods\PrivateInFinalClass` to use more appropriate message when detecting a `protected` method in an anonymous class ([#890]), by [@localheinz] +- Adjusted `Methods\PrivateInFinalClass` to ignore `protected` methods from traits([#891]), by [@localheinz] ## [`2.5.0`][2.5.0] @@ -554,6 +555,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0]. [#882]: https://github.com/ergebnis/phpstan-rules/pull/882 [#889]: https://github.com/ergebnis/phpstan-rules/pull/889 [#890]: https://github.com/ergebnis/phpstan-rules/pull/890 +[#891]: https://github.com/ergebnis/phpstan-rules/pull/891 [@enumag]: https://github.com/enumag [@ergebnis]: https://github.com/ergebnis diff --git a/src/Methods/PrivateInFinalClassRule.php b/src/Methods/PrivateInFinalClassRule.php index 37e01d15..484089fc 100644 --- a/src/Methods/PrivateInFinalClassRule.php +++ b/src/Methods/PrivateInFinalClassRule.php @@ -54,6 +54,10 @@ public function processNode( return []; } + if (self::methodIsDeclaredByTrait($containingClass, $methodName)) { + return []; + } + /** @var Reflection\ClassReflection $classReflection */ $classReflection = $scope->getClassReflection(); @@ -99,4 +103,17 @@ private static function methodIsDeclaredByParentClass( return true; } + + private static function methodIsDeclaredByTrait( + Reflection\ClassReflection $containingClass, + string $methodName + ): bool { + foreach ($containingClass->getTraits() as $trait) { + if ($trait->hasMethod($methodName)) { + return true; + } + } + + return false; + } } diff --git a/test/Integration/Methods/PrivateInFinalClassRuleTest.php b/test/Integration/Methods/PrivateInFinalClassRuleTest.php index 535ff484..0903c370 100644 --- a/test/Integration/Methods/PrivateInFinalClassRuleTest.php +++ b/test/Integration/Methods/PrivateInFinalClassRuleTest.php @@ -34,20 +34,6 @@ public function testPrivateInFinalClassRule(): void $this->analyse( self::phpFilesIn(__DIR__ . '/../../Fixture/Methods/PrivateInFinalClassRule'), [ - [ - \sprintf( - 'Method %s::method() is protected, but since the containing class is final, it can be private.', - Test\Fixture\Methods\PrivateInFinalClassRule\FinalClassImplementingAbstractProtectedMethodFromTrait::class, - ), - 11, - ], - [ - \sprintf( - 'Method %s::method() is protected, but since the containing class is final, it can be private.', - Test\Fixture\Methods\PrivateInFinalClassRule\FinalClassOverridingProtectedMethodFromTrait::class, - ), - 11, - ], [ \sprintf( 'Method %s::method() is protected, but since the containing class is final, it can be private.', @@ -55,29 +41,10 @@ public function testPrivateInFinalClassRule(): void ), 9, ], - [ - \sprintf( - 'Method %s::method() is protected, but since the containing class is final, it can be private.', - Test\Fixture\Methods\PrivateInFinalClassRule\FinalClassWithProtectedMethodFromTrait::class, - ), - 9, - ], [ 'Method method() in anonymous class is protected, but since the containing class is final, it can be private.', 8, ], - [ - 'Method method() in anonymous class is protected, but since the containing class is final, it can be private.', - 9, - ], - [ - 'Method method() in anonymous class is protected, but since the containing class is final, it can be private.', - 20, - ], - [ - 'Method method() in anonymous class is protected, but since the containing class is final, it can be private.', - 28, - ], ], ); }