From a8322b2b8ea7aece4178a70fb6bfc6b03d6d41e3 Mon Sep 17 00:00:00 2001 From: "Eirik S. Morland" Date: Sun, 21 Nov 2021 05:31:14 +0100 Subject: [PATCH] Resolve deprecated tag also from parents --- src/PhpDoc/ResolvedPhpDocBlock.php | 22 ++++++++++++++- .../Annotations/DeprecatedAnnotationsTest.php | 7 +++++ .../data/annotations-deprecated.php | 28 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/PhpDoc/ResolvedPhpDocBlock.php b/src/PhpDoc/ResolvedPhpDocBlock.php index bba06a95fd..011d5c060a 100644 --- a/src/PhpDoc/ResolvedPhpDocBlock.php +++ b/src/PhpDoc/ResolvedPhpDocBlock.php @@ -3,6 +3,7 @@ namespace PHPStan\PhpDoc; use PHPStan\Analyser\NameScope; +use PHPStan\PhpDoc\Tag\DeprecatedTag; use PHPStan\PhpDoc\Tag\MixinTag; use PHPStan\PhpDoc\Tag\ParamTag; use PHPStan\PhpDoc\Tag\ReturnTag; @@ -189,7 +190,7 @@ public function merge(array $parents, array $parentPhpDocBlocks): self $result->mixinTags = $this->getMixinTags(); $result->typeAliasTags = $this->getTypeAliasTags(); $result->typeAliasImportTags = $this->getTypeAliasImportTags(); - $result->deprecatedTag = $this->getDeprecatedTag(); + $result->deprecatedTag = self::mergeDeprecatedTags($this->getDeprecatedTag(), $parents); $result->isDeprecated = $result->deprecatedTag !== null; $result->isInternal = $this->isInternal(); $result->isFinal = $this->isFinal(); @@ -633,6 +634,25 @@ private static function mergeOneParentReturnTag(?ReturnTag $returnTag, self $par return self::resolveTemplateTypeInTag($parentReturnTag->toImplicit(), $phpDocBlock); } + /** + * @param array $parents + */ + private static function mergeDeprecatedTags(?DeprecatedTag $deprecatedTag, array $parents): ?DeprecatedTag + { + if ($deprecatedTag !== null) { + return $deprecatedTag; + } + foreach ($parents as $parent) { + $result = $parent->getDeprecatedTag(); + if ($result === null) { + continue; + } + return $result; + } + + return null; + } + /** * @param array $parents */ diff --git a/tests/PHPStan/Reflection/Annotations/DeprecatedAnnotationsTest.php b/tests/PHPStan/Reflection/Annotations/DeprecatedAnnotationsTest.php index ea25a9d06f..ffdc198290 100644 --- a/tests/PHPStan/Reflection/Annotations/DeprecatedAnnotationsTest.php +++ b/tests/PHPStan/Reflection/Annotations/DeprecatedAnnotationsTest.php @@ -131,4 +131,11 @@ public function testNonDeprecatedNativeFunctions(): void $this->assertFalse($reflectionProvider->getFunction(new Name('function_exists'), null)->isDeprecated()->yes()); } + public function testDeprecatedMethodsFromInterface(): void + { + $reflectionProvider = $this->createReflectionProvider(); + $class = $reflectionProvider->getClass(\DeprecatedAnnotations\DeprecatedBar::class); + $this->assertTrue($class->getNativeMethod('superDeprecated')->isDeprecated()->yes()); + } + } diff --git a/tests/PHPStan/Reflection/Annotations/data/annotations-deprecated.php b/tests/PHPStan/Reflection/Annotations/data/annotations-deprecated.php index 0d4db04b06..1095002d92 100644 --- a/tests/PHPStan/Reflection/Annotations/data/annotations-deprecated.php +++ b/tests/PHPStan/Reflection/Annotations/data/annotations-deprecated.php @@ -187,3 +187,31 @@ public function deprecatedFoo() { } } + +/** + * @deprecated This is totally deprecated. + */ +interface BarInterface +{ + + /** + * @deprecated This is totally deprecated. + */ + public function superDeprecated(); + +} + +/** + * {@inheritdoc} + */ +class DeprecatedBar implements BarInterface +{ + + /** + * {@inheritdoc} + */ + public function superDeprecated() + { + } + +}