Skip to content
Merged
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
4 changes: 3 additions & 1 deletion src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ private function processStmtNode(
true,
$param,
false,
$scope->isInTrait(),
), $methodScope);
}
}
Expand Down Expand Up @@ -628,7 +629,7 @@ private function processStmtNode(
$this->processAttributeGroups($stmt->attrGroups, $classScope, $classStatementsGatherer);

$this->processStmtNodes($stmt, $stmt->stmts, $classScope, $classStatementsGatherer);
$nodeCallback(new ClassPropertiesNode($stmt, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getTraitProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls()), $classScope);
$nodeCallback(new ClassPropertiesNode($stmt, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls()), $classScope);
$nodeCallback(new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls()), $classScope);
$nodeCallback(new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches()), $classScope);
$classReflection->evictPrivateSymbols();
Expand All @@ -650,6 +651,7 @@ private function processStmtNode(
false,
$prop,
$isReadOnly,
$scope->isInTrait(),
),
$scope,
);
Expand Down
26 changes: 26 additions & 0 deletions src/Node/ClassMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

namespace PHPStan\Node;

class ClassMethod
{

public function __construct(
private \PhpParser\Node\Stmt\ClassMethod $node,
private bool $isDeclaredInTrait,
)
{
}


public function getNode(): \PhpParser\Node\Stmt\ClassMethod
{
return $this->node;
}

public function isDeclaredInTrait(): bool
{
return $this->isDeclaredInTrait;
}

}
1 change: 0 additions & 1 deletion src/Node/ClassMethodsNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace PHPStan\Node;

use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\NodeAbstract;
use PHPStan\Node\Method\MethodCall;

Expand Down
14 changes: 2 additions & 12 deletions src/Node/ClassPropertiesNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use PHPStan\Type\ObjectType;
use function array_key_exists;
use function array_keys;
use function array_merge;
use function count;
use function in_array;

Expand All @@ -31,11 +30,10 @@ class ClassPropertiesNode extends NodeAbstract implements VirtualNode

/**
* @param ClassPropertyNode[] $properties
* @param ClassPropertyNode[] $traitProperties
* @param array<int, PropertyRead|PropertyWrite> $propertyUsages
* @param array<int, MethodCall> $methodCalls
*/
public function __construct(private ClassLike $class, private array $properties, private array $traitProperties, private array $propertyUsages, private array $methodCalls)
public function __construct(private ClassLike $class, private array $properties, private array $propertyUsages, private array $methodCalls)
{
parent::__construct($class->getAttributes());
}
Expand All @@ -53,14 +51,6 @@ public function getProperties(): array
return $this->properties;
}

/**
* @return ClassPropertyNode[]
*/
public function getTraitProperties(): array
{
return $this->traitProperties;
}

/**
* @return array<int, PropertyRead|PropertyWrite>
*/
Expand Down Expand Up @@ -102,7 +92,7 @@ public function getUninitializedProperties(
$classReflection = $scope->getClassReflection();

$properties = [];
foreach (array_merge($this->getProperties(), $this->getTraitProperties()) as $property) {
foreach ($this->getProperties() as $property) {
if ($property->isStatic()) {
continue;
}
Expand Down
6 changes: 6 additions & 0 deletions src/Node/ClassPropertyNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function __construct(
private bool $isPromoted,
Node $originalNode,
private bool $isReadonlyByPhpDoc,
private bool $isDeclaredInTrait,
)
{
parent::__construct($originalNode->getAttributes());
Expand Down Expand Up @@ -83,6 +84,11 @@ public function isReadOnlyByPhpDoc(): bool
return $this->isReadonlyByPhpDoc;
}

public function isDeclaredInTrait(): bool
{
return $this->isDeclaredInTrait;
}

/**
* @return Identifier|Name|Node\ComplexType|null
*/
Expand Down
31 changes: 5 additions & 26 deletions src/Node/ClassStatementsGatherer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ class ClassStatementsGatherer
/** @var ClassPropertyNode[] */
private array $properties = [];

/** @var ClassPropertyNode[] */
private array $traitProperties = [];

/** @var Node\Stmt\ClassMethod[] */
/** @var ClassMethod[] */
private array $methods = [];

/** @var \PHPStan\Node\Method\MethodCall[] */
Expand Down Expand Up @@ -66,15 +63,7 @@ public function getProperties(): array
}

/**
* @return ClassPropertyNode[]
*/
public function getTraitProperties(): array
{
return $this->traitProperties;
}

/**
* @return Node\Stmt\ClassMethod[]
* @return ClassMethod[]
*/
public function getMethods(): array
{
Expand Down Expand Up @@ -128,7 +117,7 @@ private function gatherNodes(Node $node, Scope $scope): void
if ($scope->getClassReflection()->getName() !== $this->classReflection->getName()) {
return;
}
if ($node instanceof ClassPropertyNode && !$scope->isInTrait()) {
if ($node instanceof ClassPropertyNode) {
$this->properties[] = $node;
if ($node->isPromoted()) {
$this->propertyUsages[] = new PropertyWrite(
Expand All @@ -138,18 +127,8 @@ private function gatherNodes(Node $node, Scope $scope): void
}
return;
}
if ($node instanceof ClassPropertyNode && $scope->isInTrait()) {
$this->traitProperties[] = $node;
if ($node->isPromoted()) {
$this->propertyUsages[] = new PropertyWrite(
new PropertyFetch(new Expr\Variable('this'), new Identifier($node->getName())),
$scope,
);
}
return;
}
if ($node instanceof Node\Stmt\ClassMethod && !$scope->isInTrait()) {
$this->methods[] = $node;
if ($node instanceof Node\Stmt\ClassMethod) {
$this->methods[] = new ClassMethod($node, $scope->isInTrait());
return;
}
if ($node instanceof Node\Stmt\ClassConst) {
Expand Down
15 changes: 9 additions & 6 deletions src/Rules/DeadCode/UnusedPrivateMethodRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,20 @@ public function processNode(Node $node, Scope $scope): array

$methods = [];
foreach ($node->getMethods() as $method) {
if (!$method->isPrivate()) {
if (!$method->getNode()->isPrivate()) {
continue;
}
$methodName = $method->name->toString();
if ($method->isDeclaredInTrait()) {
continue;
}
$methodName = $method->getNode()->name->toString();
if ($constructor !== null && $constructor->getName() === $methodName) {
continue;
}
if (strtolower($methodName) === '__clone') {
continue;
}
$methods[$method->name->toString()] = $method;
$methods[$methodName] = $method;
}

$arrayCalls = [];
Expand Down Expand Up @@ -146,13 +149,13 @@ public function processNode(Node $node, Scope $scope): array
}

$errors = [];
foreach ($methods as $methodName => $methodNode) {
foreach ($methods as $methodName => $method) {
$methodType = 'Method';
if ($methodNode->isStatic()) {
if ($method->getNode()->isStatic()) {
$methodType = 'Static method';
}
$errors[] = RuleErrorBuilder::message(sprintf('%s %s::%s() is unused.', $methodType, $classReflection->getDisplayName(), $methodName))
->line($methodNode->getLine())
->line($method->getNode()->getLine())
->identifier('deadCode.unusedMethod')
->metadata([
'classOrder' => $node->getClass()->getAttribute('statementOrder'),
Expand Down
3 changes: 3 additions & 0 deletions src/Rules/DeadCode/UnusedPrivatePropertyRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public function processNode(Node $node, Scope $scope): array
if (!$property->isPrivate()) {
continue;
}
if ($property->isDeclaredInTrait()) {
continue;
}

$alwaysRead = false;
$alwaysWritten = false;
Expand Down