diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 6b8fded992..3042f008bf 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -737,6 +737,11 @@ public function isFinal(): bool return $this->isFinal; } + public function isFinalByKeyword(): bool + { + return $this->reflection->isFinal(); + } + public function getTemplateTypeMap(): TemplateTypeMap { if ($this->templateTypeMap !== null) { diff --git a/src/Rules/Classes/ExistingClassInClassExtendsRule.php b/src/Rules/Classes/ExistingClassInClassExtendsRule.php index f00c1b75d9..b23c0a5bd1 100644 --- a/src/Rules/Classes/ExistingClassInClassExtendsRule.php +++ b/src/Rules/Classes/ExistingClassInClassExtendsRule.php @@ -66,7 +66,7 @@ public function processNode(Node $node, Scope $scope): array $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $extendedClassName ))->nonIgnorable()->build(); - } elseif ($reflection->isFinal()) { + } elseif ($reflection->isFinalByKeyword()) { $messages[] = RuleErrorBuilder::message(sprintf( '%s extends final class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', diff --git a/tests/PHPStan/Rules/Classes/data/extends-implements.php b/tests/PHPStan/Rules/Classes/data/extends-implements.php index 58f3e0b800..64d23563d1 100644 --- a/tests/PHPStan/Rules/Classes/data/extends-implements.php +++ b/tests/PHPStan/Rules/Classes/data/extends-implements.php @@ -31,3 +31,16 @@ interface BazInterface extends FOOInterface { } + +/** + * @final + */ +class FinalWithAnnotation +{ + +} + +class ExtendsFinalWithAnnotation extends FinalWithAnnotation +{ + +} diff --git a/tests/PHPStan/Rules/Methods/data/overriding-method.php b/tests/PHPStan/Rules/Methods/data/overriding-method.php index d26ea5cfcd..961da3439b 100644 --- a/tests/PHPStan/Rules/Methods/data/overriding-method.php +++ b/tests/PHPStan/Rules/Methods/data/overriding-method.php @@ -283,3 +283,26 @@ public function __construct() } } + +class FinalWithAnnotation +{ + + /** + * @final + */ + public function doFoo() + { + + } + +} + +class ExtendsFinalWithAnnotation extends FinalWithAnnotation +{ + + public function doFoo() + { + + } + +}