You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm happy to implement a solution here, just not sure of the best approach. I think the most precise solution is to check if the $node in PrivateInFinalClass has a Before attribute. Maybe this should be configurable at some point 🤷
Steps required to reproduce the problem
I have a test class written like this:
namespaceTests\Feature\Models;
useApp\Models\User;
useIlluminate\Database\Eloquent\Model;
useIlluminate\Foundation\Testing\LazilyRefreshDatabase;
usePHPUnit\Framework\Attributes\Before;
usePHPUnit\Framework\Attributes\CoversClass;
useTests\TestCase;
#[CoversClass(User::class)]
finalclass UserTest extends TestCase
{
use LazilyRefreshDatabase;
#[Before(1)]
protectedfunctionunguardModel(): void
{
Model::unguard();
}
// ... test cases here
}
Expected Result
No warning should be raised from PHPStan.
Actual Result
When running PHPStan with the PrivateInFinalClassRule, it tells me that this method can be private. However, if I convert the error to private, PHPUnit fails because Error: Call to private method Tests\Feature\Models\UserTest::unguardModels() from scope PHPUnit\Framework\TestCase.
Suggested Change
declare(strict_types=1);
/** * Copyright (c) 2018-2024 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. * * @see https://github.com/ergebnis/phpstan-rules */namespaceErgebnis\PHPStan\Rules\Methods;
usePhpParser\Node;
usePHPStan\Analyser;
usePHPStan\Reflection;
usePHPStan\Rules;
usePHPStan\ShouldNotHappenException;
finalclass PrivateInFinalClassRule implementsRules\Rule
{
privatestatic$attributesThatIndicateProtectedIsOk = [
\PHPUnit\Framework\Attributes\Before::class
];
publicfunctiongetNodeType(): string
{
returnNode\Stmt\ClassMethod::class;
}
publicfunctionprocessNode(
Node$node,
Analyser\Scope$scope,
): array {
if (!$nodeinstanceofNode\Stmt\ClassMethod) {
thrownewShouldNotHappenException(\sprintf(
'Expected node to be instance of "%s", but got instance of "%s" instead.',
Node\Stmt\ClassMethod::class,
$node::class,
));
}
/** @var Reflection\ClassReflection $containingClass */$containingClass = $scope->getClassReflection();
if (!$containingClass->isFinal()) {
return [];
}
if ($node->isPublic()) {
return [];
}
if ($node->isPrivate()) {
return [];
}
// Check attributesforeach($node->attrGroupsas$attrGroup) {
foreach($attrGroup->attrsas$attr) {
if (in_array($attr->name->toString(), self::$attributesThatIndicateProtectedIsOk)) {
return [];
}
}
}
$methodName = $node->name->toString();
$parentClass = $containingClass->getNativeReflection()->getParentClass();
if ($parentClassinstanceof \ReflectionClass && $parentClass->hasMethod($methodName)) {
$parentMethod = $parentClass->getMethod($methodName);
if ($parentMethod->isProtected()) {
return [];
}
}
$ruleErrorBuilder = Rules\RuleErrorBuilder::message(\sprintf(
'Method %s::%s() is protected, but since the containing class is final, it can be private.',
$containingClass->getName(),
$methodName,
));
return [
$ruleErrorBuilder->build(),
];
}
}
The text was updated successfully, but these errors were encountered:
I'm happy to implement a solution here, just not sure of the best approach. I think the most precise solution is to check if the $node in PrivateInFinalClass has a Before attribute. Maybe this should be configurable at some point 🤷
Steps required to reproduce the problem
I have a test class written like this:
Expected Result
No warning should be raised from PHPStan.
Actual Result
When running PHPStan with the PrivateInFinalClassRule, it tells me that this method can be private. However, if I convert the error to private, PHPUnit fails because
Error: Call to private method Tests\Feature\Models\UserTest::unguardModels() from scope PHPUnit\Framework\TestCase
.Suggested Change
The text was updated successfully, but these errors were encountered: