Skip to content

Commit 7042805

Browse files
authored
Implement AbstractPrivateMethodRule
1 parent b77f894 commit 7042805

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

conf/config.level0.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ rules:
8080
- PHPStan\Rules\Functions\VariadicParametersDeclarationRule
8181
- PHPStan\Rules\Keywords\ContinueBreakInLoopRule
8282
- PHPStan\Rules\Methods\AbstractMethodInNonAbstractClassRule
83+
- PHPStan\Rules\Methods\AbstractPrivateMethodRule
8384
- PHPStan\Rules\Methods\CallMethodsRule
8485
- PHPStan\Rules\Methods\CallStaticMethodsRule
8586
- PHPStan\Rules\Methods\ConstructorReturnTypeRule
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Methods;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Node\InClassMethodNode;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Rules\RuleErrorBuilder;
10+
use function sprintf;
11+
12+
/** @implements Rule<InClassMethodNode> */
13+
class AbstractPrivateMethodRule implements Rule
14+
{
15+
16+
public function getNodeType(): string
17+
{
18+
return InClassMethodNode::class;
19+
}
20+
21+
public function processNode(Node $node, Scope $scope): array
22+
{
23+
$method = $node->getMethodReflection();
24+
25+
if (!$method->isPrivate()) {
26+
return [];
27+
}
28+
29+
if (!$method->isAbstract()->yes()) {
30+
return [];
31+
}
32+
33+
if ($scope->isInTrait()) {
34+
return [];
35+
}
36+
37+
$classReflection = $scope->getClassReflection();
38+
if ($classReflection === null) {
39+
return [];
40+
}
41+
42+
if (!$classReflection->isAbstract() && !$classReflection->isInterface()) {
43+
return [];
44+
}
45+
46+
return [
47+
RuleErrorBuilder::message(sprintf(
48+
'Private method %s::%s() cannot be abstract.',
49+
$method->getDeclaringClass()->getDisplayName(),
50+
$method->getName(),
51+
))->nonIgnorable()->build(),
52+
];
53+
}
54+
55+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Methods;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/** @extends RuleTestCase<AbstractPrivateMethodRule> */
9+
class AbstractPrivateMethodRuleTest extends RuleTestCase
10+
{
11+
12+
protected function getRule(): Rule
13+
{
14+
return new AbstractPrivateMethodRule();
15+
}
16+
17+
public function testRule(): void
18+
{
19+
$this->analyse([__DIR__ . '/data/abstract-private-method.php'], [
20+
[
21+
'Private method PrivateAbstractMethod\HelloWorld::sayPrivate() cannot be abstract.',
22+
12,
23+
],
24+
[
25+
'Private method PrivateAbstractMethod\fooInterface::sayPrivate() cannot be abstract.',
26+
24,
27+
],
28+
]);
29+
}
30+
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PrivateAbstractMethod;
4+
5+
abstract class HelloWorld
6+
{
7+
public function doFoo(): void {
8+
$this->sayHello();
9+
$this->sayWorld();
10+
}
11+
12+
abstract private function sayPrivate() : void;
13+
abstract protected function sayProtected() : void;
14+
abstract public function sayPublic() : void;
15+
}
16+
17+
trait fooTrait{
18+
abstract private function sayPrivate() : void;
19+
abstract protected function sayProtected() : void;
20+
abstract public function sayPublic() : void;
21+
}
22+
23+
interface fooInterface {
24+
abstract private function sayPrivate() : void;
25+
abstract protected function sayProtected() : void;
26+
abstract public function sayPublic() : void;
27+
}

0 commit comments

Comments
 (0)