From c86e460e93cfe0f2d39a175c71923257d5a07d7f Mon Sep 17 00:00:00 2001 From: Brad <28307684+mad-briller@users.noreply.github.com> Date: Fri, 28 Oct 2022 10:10:02 +0100 Subject: [PATCH] Fix covers rule for functions. --- src/Rules/PHPUnit/CoversHelper.php | 14 +++++++++++--- .../PHPUnit/ClassMethodCoversExistsRuleTest.php | 4 ++-- tests/Rules/PHPUnit/data/class-coverage.php | 12 ++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Rules/PHPUnit/CoversHelper.php b/src/Rules/PHPUnit/CoversHelper.php index aebe000..2346946 100644 --- a/src/Rules/PHPUnit/CoversHelper.php +++ b/src/Rules/PHPUnit/CoversHelper.php @@ -3,6 +3,7 @@ namespace PHPStan\Rules\PHPUnit; use PhpParser\Node; +use PhpParser\Node\Name; use PHPStan\PhpDoc\ResolvedPhpDocBlock; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; use PHPStan\Reflection\ReflectionProvider; @@ -70,8 +71,9 @@ public function processCovers( { $errors = []; $covers = (string) $phpDocTag->value; + $isMethod = strpos($covers, '::') !== false; - if (strpos($covers, '::') !== false) { + if ($isMethod) { [$className, $method] = explode('::', $covers); } else { $className = $covers; @@ -83,6 +85,7 @@ public function processCovers( if ($this->reflectionProvider->hasClass($className)) { $class = $this->reflectionProvider->getClass($className); + if (isset($method) && $method !== '' && !$class->hasMethod($method)) { $errors[] = RuleErrorBuilder::message(sprintf( '@covers value %s references an invalid method.', @@ -90,9 +93,14 @@ public function processCovers( ))->build(); } } else { + if (!isset($method) && $this->reflectionProvider->hasFunction(new Name($covers, []), null)) { + return $errors; + } + $errors[] = RuleErrorBuilder::message(sprintf( - '@covers value %s references an invalid class.', - $covers + '@covers value %s references an invalid %s.', + $covers, + $isMethod ? 'method' : 'class or function' ))->build(); } return $errors; diff --git a/tests/Rules/PHPUnit/ClassMethodCoversExistsRuleTest.php b/tests/Rules/PHPUnit/ClassMethodCoversExistsRuleTest.php index 2e09326..5764a60 100644 --- a/tests/Rules/PHPUnit/ClassMethodCoversExistsRuleTest.php +++ b/tests/Rules/PHPUnit/ClassMethodCoversExistsRuleTest.php @@ -26,7 +26,7 @@ public function testRule(): void { $this->analyse([__DIR__ . '/data/method-coverage.php'], [ [ - '@covers value ::ignoreThis references an invalid class.', + '@covers value ::ignoreThis references an invalid method.', 14, ], [ @@ -34,7 +34,7 @@ public function testRule(): void 28, ], [ - '@covers value \Not\A\Class::foo references an invalid class.', + '@covers value \Not\A\Class::foo references an invalid method.', 35, ], [ diff --git a/tests/Rules/PHPUnit/data/class-coverage.php b/tests/Rules/PHPUnit/data/class-coverage.php index c35cd26..44ea6b4 100644 --- a/tests/Rules/PHPUnit/data/class-coverage.php +++ b/tests/Rules/PHPUnit/data/class-coverage.php @@ -23,3 +23,15 @@ class CoversShouldExistTestCase2 extends \PHPUnit\Framework\TestCase class MultipleCoversDefaultClass extends \PHPUnit\Framework\TestCase { } + +/** + * @covers \ClassCoverage\testable + */ +class CoversFunction extends \PHPUnit\Framework\TestCase +{ +} + +function testable(): void +{ + +}