Skip to content
Closed
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion src/Rules/DeadCode/UnusedPrivateConstantRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ public function processNode(Node $node, Scope $scope): array
}

$classReflection = $node->getClassReflection();
$isClassFinal = $classReflection->isFinalByKeyword();
$classType = new ObjectType($classReflection->getName(), classReflection: $classReflection);

$constants = [];
foreach ($node->getConstants() as $constant) {
if (!$constant->isPrivate()) {
if ($constant->isPublic() || ($constant->isProtected() && !$isClassFinal)) {
continue;
}

Expand Down
11 changes: 9 additions & 2 deletions src/Rules/DeadCode/UnusedPrivateMethodRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function processNode(Node $node, Scope $scope): array
return [];
}
$classReflection = $node->getClassReflection();
$isClassFinal = $classReflection->isFinalByKeyword();
$classType = new ObjectType($classReflection->getName(), classReflection: $classReflection);
$constructor = null;
if ($classReflection->hasConstructor()) {
Expand All @@ -48,13 +49,15 @@ public function processNode(Node $node, Scope $scope): array

$methods = [];
foreach ($node->getMethods() as $method) {
if (!$method->getNode()->isPrivate()) {
$methodNode = $method->getNode();
if ($methodNode->isPublic() || ($methodNode->isProtected() && !$isClassFinal)) {
continue;
}
if ($method->isDeclaredInTrait()) {
continue;
}
$methodName = $method->getNode()->name->toString();

$methodName = $methodNode->name->toString();
if ($constructor !== null && $constructor->getName() === $methodName) {
continue;
}
Expand All @@ -63,6 +66,10 @@ public function processNode(Node $node, Scope $scope): array
}

$methodReflection = $classReflection->getNativeMethod($methodName);
if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) {
continue;
}

foreach ($this->extensionProvider->getExtensions() as $extension) {
if ($extension->isAlwaysUsed($methodReflection)) {
continue 2;
Expand Down
6 changes: 5 additions & 1 deletion src/Rules/DeadCode/UnusedPrivatePropertyRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ public function processNode(Node $node, Scope $scope): array
return [];
}
$classReflection = $node->getClassReflection();
$isClassFinal = $classReflection->isFinalByKeyword();
$classType = new ObjectType($classReflection->getName(), classReflection: $classReflection);
$properties = [];
foreach ($node->getProperties() as $property) {
if (!$property->isPrivate()) {
if ($property->isPublic() || ($property->isProtected() && !$isClassFinal)) {
continue;
}
if ($property->isDeclaredInTrait()) {
Expand Down Expand Up @@ -96,6 +97,9 @@ public function processNode(Node $node, Scope $scope): array
}

$propertyReflection = $classReflection->getNativeProperty($propertyName);
if ($propertyReflection->getDeclaringClass()->getName() !== $classReflection->getName()) {
continue;
}

foreach ($this->extensionProvider->getExtensions() as $extension) {
if ($alwaysRead && $alwaysWritten) {
Expand Down
16 changes: 16 additions & 0 deletions tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ public function testRule(): void
]);
}

public function testProtected(): void
{
$this->analyse([__DIR__ . '/data/unused-protected-constant.php'], [
[
'Constant UnusedProtectedConstant\Bar::BAR_CONST is unused.',
26,
'See: https://phpstan.org/developing-extensions/always-used-class-constants',
],
[
'Constant UnusedProtectedConstant\Bar::BAZ_CONST is unused.',
28,
'See: https://phpstan.org/developing-extensions/always-used-class-constants',
],
]);
}

public function testBug5651(): void
{
$this->analyse([__DIR__ . '/data/bug-5651.php'], []);
Expand Down
14 changes: 14 additions & 0 deletions tests/PHPStan/Rules/DeadCode/UnusedPrivateMethodRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ public function testRule(): void
]);
}

public function testProtected(): void
{
$this->analyse([__DIR__ . '/data/unused-protected-method.php'], [
[
'Method UnusedProtectedMethod\Bar::unused1() is unused.',
30,
],
[
'Method UnusedProtectedMethod\Bar::unused2() is unused.',
35,
],
]);
}

public function testBug3630(): void
{
$this->analyse([__DIR__ . '/data/bug-3630.php'], []);
Expand Down
18 changes: 18 additions & 0 deletions tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,24 @@ public function testTrait(): void
$this->analyse([__DIR__ . '/data/private-property-trait.php'], []);
}

public function testProtected(): void
{
$this->alwaysWrittenTags = [];
$this->alwaysReadTags = [];
$this->analyse([__DIR__ . '/data/unused-protected-property.php'], [
[
'Property UnusedProtectedProperty\Bar::$bar is unused.',
31,
'See: https://phpstan.org/developing-extensions/always-read-written-properties',
],
[
'Property UnusedProtectedProperty\Bar::$baz is unused.',
33,
'See: https://phpstan.org/developing-extensions/always-read-written-properties',
],
]);
}

public function testBug3636(): void
{
$this->alwaysWrittenTags = [];
Expand Down
35 changes: 35 additions & 0 deletions tests/PHPStan/Rules/DeadCode/data/unused-protected-constant.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php // lint >= 8.1

namespace UnusedProtectedConstant;

class Foo
{

protected const FOO_CONST = 1;

protected const BAR_CONST = 2;

final protected const BAZ_CONST = 2;

public function doFoo()
{
echo self::FOO_CONST;
}

}

final class Bar
{

protected const FOO_CONST = 1;

protected const BAR_CONST = 2;

final protected const BAZ_CONST = 2;

public function doFoo()
{
echo self::FOO_CONST;
}

}
40 changes: 40 additions & 0 deletions tests/PHPStan/Rules/DeadCode/data/unused-protected-method.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace UnusedProtectedMethod;

class Foo
{
protected function used1()
{
}

protected function unused1()
{
$this->used1();
}

final protected function unused2()
{
$this->used1();
}

}

final class Bar
{

protected function used1()
{
}

protected function unused1()
{
$this->used1();
}

final protected function unused2()
{
$this->used1();
}

}
45 changes: 45 additions & 0 deletions tests/PHPStan/Rules/DeadCode/data/unused-protected-property.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php // lint >= 8.4

namespace UnusedProtectedProperty;

class Foo
{

protected $foo;

protected string $bar;

final protected string $baz;

public function __construct()
{
$this->foo = 1;
}

public function getFoo()
{
return $this->foo;
}

}

final class Bar
{

protected $foo;

protected string $bar;

final protected string $baz;

public function __construct()
{
$this->foo = 1;
}

public function getFoo()
{
return $this->foo;
}

}
Loading