diff --git a/composer-require-checker.json b/composer-require-checker.json index 0dc15360..c1fa2577 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -33,6 +33,10 @@ "PHPStan\\Rules\\Rule", "PHPStan\\Rules\\RuleError", "PHPStan\\Rules\\RuleErrorBuilder", + "PHPUnit\\Framework\\Attributes\\After", + "PHPUnit\\Framework\\Attributes\\Before", + "PHPUnit\\Framework\\Attributes\\PostCondition", + "PHPUnit\\Framework\\Attributes\\PreCondition", "self", "string", "true" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e2e011fd..ac0ddfff 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -20,3 +20,23 @@ parameters: count: 1 path: src/Functions/NoNullableReturnTypeDeclarationRule.php + - + message: "#^Class PHPUnit\\\\Framework\\\\Attributes\\\\After not found\\.$#" + count: 1 + path: src/Methods/PrivateInFinalClassRule.php + + - + message: "#^Class PHPUnit\\\\Framework\\\\Attributes\\\\Before not found\\.$#" + count: 1 + path: src/Methods/PrivateInFinalClassRule.php + + - + message: "#^Class PHPUnit\\\\Framework\\\\Attributes\\\\PostCondition not found\\.$#" + count: 1 + path: src/Methods/PrivateInFinalClassRule.php + + - + message: "#^Class PHPUnit\\\\Framework\\\\Attributes\\\\PreCondition not found\\.$#" + count: 1 + path: src/Methods/PrivateInFinalClassRule.php + diff --git a/src/Methods/PrivateInFinalClassRule.php b/src/Methods/PrivateInFinalClassRule.php index 484089fc..d7c01c6f 100644 --- a/src/Methods/PrivateInFinalClassRule.php +++ b/src/Methods/PrivateInFinalClassRule.php @@ -18,6 +18,7 @@ use PHPStan\Analyser; use PHPStan\Reflection; use PHPStan\Rules; +use PHPUnit\Framework; /** * @implements Rules\Rule @@ -48,6 +49,10 @@ public function processNode( return []; } + if (self::methodHasPhpUnitAttributeWhichRequiresProtectedVisibility($node)) { + return []; + } + $methodName = $node->name->toString(); if (self::methodIsDeclaredByParentClass($containingClass, $methodName)) { @@ -87,6 +92,26 @@ public function processNode( ]; } + private static function methodHasPhpUnitAttributeWhichRequiresProtectedVisibility(Node\Stmt\ClassMethod $node): bool + { + $attributes = [ + Framework\Attributes\Before::class, + Framework\Attributes\After::class, + Framework\Attributes\PostCondition::class, + Framework\Attributes\PreCondition::class, + ]; + + foreach ($node->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attribute) { + if (\in_array($attribute->name->toString(), $attributes, true)) { + return true; + } + } + } + + return false; + } + private static function methodIsDeclaredByParentClass( Reflection\ClassReflection $containingClass, string $methodName diff --git a/test/Fixture/Methods/PrivateInFinalClassRule/FinalClassWithProtectedMethodsWithPhpUnitAttributes.php b/test/Fixture/Methods/PrivateInFinalClassRule/FinalClassWithProtectedMethodsWithPhpUnitAttributes.php new file mode 100644 index 00000000..9acd987c --- /dev/null +++ b/test/Fixture/Methods/PrivateInFinalClassRule/FinalClassWithProtectedMethodsWithPhpUnitAttributes.php @@ -0,0 +1,30 @@ +