Skip to content

Commit

Permalink
Implement AbstractPrivateMethodRule
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored Nov 21, 2023
1 parent b77f894 commit 7042805
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ rules:
- PHPStan\Rules\Functions\VariadicParametersDeclarationRule
- PHPStan\Rules\Keywords\ContinueBreakInLoopRule
- PHPStan\Rules\Methods\AbstractMethodInNonAbstractClassRule
- PHPStan\Rules\Methods\AbstractPrivateMethodRule
- PHPStan\Rules\Methods\CallMethodsRule
- PHPStan\Rules\Methods\CallStaticMethodsRule
- PHPStan\Rules\Methods\ConstructorReturnTypeRule
Expand Down
55 changes: 55 additions & 0 deletions src/Rules/Methods/AbstractPrivateMethodRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use function sprintf;

/** @implements Rule<InClassMethodNode> */
class AbstractPrivateMethodRule implements Rule
{

public function getNodeType(): string
{
return InClassMethodNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
$method = $node->getMethodReflection();

if (!$method->isPrivate()) {
return [];
}

if (!$method->isAbstract()->yes()) {
return [];
}

if ($scope->isInTrait()) {
return [];
}

$classReflection = $scope->getClassReflection();
if ($classReflection === null) {
return [];
}

if (!$classReflection->isAbstract() && !$classReflection->isInterface()) {
return [];
}

return [
RuleErrorBuilder::message(sprintf(
'Private method %s::%s() cannot be abstract.',
$method->getDeclaringClass()->getDisplayName(),
$method->getName(),
))->nonIgnorable()->build(),
];
}

}
31 changes: 31 additions & 0 deletions tests/PHPStan/Rules/Methods/AbstractPrivateMethodRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/** @extends RuleTestCase<AbstractPrivateMethodRule> */
class AbstractPrivateMethodRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new AbstractPrivateMethodRule();
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/abstract-private-method.php'], [
[
'Private method PrivateAbstractMethod\HelloWorld::sayPrivate() cannot be abstract.',
12,
],
[
'Private method PrivateAbstractMethod\fooInterface::sayPrivate() cannot be abstract.',
24,
],
]);
}

}
27 changes: 27 additions & 0 deletions tests/PHPStan/Rules/Methods/data/abstract-private-method.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

namespace PrivateAbstractMethod;

abstract class HelloWorld
{
public function doFoo(): void {
$this->sayHello();
$this->sayWorld();
}

abstract private function sayPrivate() : void;
abstract protected function sayProtected() : void;
abstract public function sayPublic() : void;
}

trait fooTrait{
abstract private function sayPrivate() : void;
abstract protected function sayProtected() : void;
abstract public function sayPublic() : void;
}

interface fooInterface {
abstract private function sayPrivate() : void;
abstract protected function sayProtected() : void;
abstract public function sayPublic() : void;
}

0 comments on commit 7042805

Please sign in to comment.