Skip to content

Update check for #[MustUseResult] on method definitions in interfaces and parent classes #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions src/Rules/MustUseResultRule.php
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
use DaveLiddament\PhpstanPhpLanguageExtensions\Helpers\Cache;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
@@ -66,11 +67,8 @@
if ($this->cache->hasEntry($fullMethodName)) {
$mustUseResult = $this->cache->getEntry($fullMethodName);
} else {
$mustUseResult = AttributeFinder::hasAttributeOnMethod(
$classReflection->getNativeReflection(),
$methodName,
MustUseResult::class,
);
$mustUseResult = $this->isMustUseResult($classReflection, $methodName);

$this->cache->addEntry($fullMethodName, $mustUseResult);
}

@@ -85,4 +83,27 @@

return [];
}

private function isMustUseResult(ClassReflection $classReflection, string $methodName): bool
{
if (AttributeFinder::hasAttributeOnMethod(
$classReflection->getNativeReflection(),

Check failure on line 90 in src/Rules/MustUseResultRule.php

GitHub Actions / Full CI checks for all supported PHP versions (highest, 8.4, ubuntu-22.04)

Parameter #1 $class of static method DaveLiddament\PhpstanPhpLanguageExtensions\AttributeValueReaders\AttributeFinder::hasAttributeOnMethod() expects ReflectionClass<object>, PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum given.
$methodName,
MustUseResult::class,
)) {
return true;
}

foreach ($classReflection->getAncestors() as $parentClassReflection) {
if (AttributeFinder::hasAttributeOnMethod(
$parentClassReflection->getNativeReflection(),

Check failure on line 99 in src/Rules/MustUseResultRule.php

GitHub Actions / Full CI checks for all supported PHP versions (highest, 8.4, ubuntu-22.04)

Parameter #1 $class of static method DaveLiddament\PhpstanPhpLanguageExtensions\AttributeValueReaders\AttributeFinder::hasAttributeOnMethod() expects ReflectionClass<object>, PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum given.
$methodName,
MustUseResult::class,
)) {
return true;
}
}

return false;
}
}
10 changes: 10 additions & 0 deletions tests/Rules/MustUseResultTest.php
Original file line number Diff line number Diff line change
@@ -35,6 +35,16 @@ public function testMustUseWithParent(): void
$this->assertIssuesReported(__DIR__.'/data/mustUseResult/mustUseResultWithParent.php');
}

public function testMustUseResultOnExtendedClass(): void
{
$this->assertIssuesReported(__DIR__.'/data/mustUseResult/mustUseResultOnExtendedClass.php');
}

public function testMustUseResultOnInterface(): void
{
$this->assertIssuesReported(__DIR__.'/data/mustUseResult/mustUseResultOnInterface.php');
}

protected function getErrorFormatter(): string
{
return 'Result returned by method must be used';
88 changes: 88 additions & 0 deletions tests/Rules/data/mustUseResult/mustUseResultOnExtendedClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace MustUseResultOnExtendedClass {


use DaveLiddament\PhpLanguageExtensions\MustUseResult;

abstract class BaseClass {

#[MustUseResult]
public function mustUseResult(): int
{
return 1;
}

#[MustUseResult]
abstract public function abstractMustUseResult(): int;

public function dontNeedToUseResult(): int
{
return 2;
}

abstract function abstractDontNeedToUseResult(): int;

}


class ExtendedOnce extends BaseClass
{

public function mustUseResult(): int
{
return parent::mustUseResult();
}

public function dontNeedToUseResult(): int
{
return parent::dontNeedToUseResult();
}

public function abstractMustUseResult(): int
{
return 1;
}

public function abstractDontNeedToUseResult(): int
{
return 2;
}
}

class ExtendedTwice extends ExtendedOnce
{
}



$extendedOnce = new ExtendedOnce();

$extendedOnce->dontNeedToUseResult(); // OK

$extendedOnce->mustUseResult(); // ERROR

$extendedOnce->abstractMustUseResult(); // ERROR

$extendedOnce->abstractDontNeedToUseResult(); // OK

echo $extendedOnce->mustUseResult(); // OK;

$value = 1 + $extendedOnce->mustUseResult(); // OK



$extendedTwice = new ExtendedTwice();

$extendedTwice->dontNeedToUseResult(); // OK

$extendedTwice->mustUseResult(); // ERROR

$extendedTwice->abstractMustUseResult(); // ERROR

$extendedTwice->abstractDontNeedToUseResult(); // OK

echo $extendedTwice->mustUseResult(); // OK;

$value = 1 + $extendedTwice->mustUseResult(); // OK
}
60 changes: 60 additions & 0 deletions tests/Rules/data/mustUseResult/mustUseResultOnInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace MustUseResultOnInterface {


use DaveLiddament\PhpLanguageExtensions\MustUseResult;

interface BaseClass {

#[MustUseResult]
public function mustUseResult(): int;

public function dontNeedToUseResult(): int;

}


class ExtendedOnce implements BaseClass
{

public function mustUseResult(): int
{
return 1;
}

public function dontNeedToUseResult(): int
{
return 2;
}

}

class ExtendedTwice extends ExtendedOnce
{
}



$extendedOnce = new ExtendedOnce();

$extendedOnce->dontNeedToUseResult(); // OK

$extendedOnce->mustUseResult(); // ERROR

echo $extendedOnce->mustUseResult(); // OK;

$value = 1 + $extendedOnce->mustUseResult(); // OK



$extendedTwice = new ExtendedTwice();

$extendedTwice->dontNeedToUseResult(); // OK

$extendedTwice->mustUseResult(); // ERROR

echo $extendedTwice->mustUseResult(); // OK;

$value = 1 + $extendedTwice->mustUseResult(); // OK
}
Loading