Skip to content

Commit 888d709

Browse files
committed
Allow debugging of usages
1 parent d5ab39a commit 888d709

21 files changed

+450
-137
lines changed

phpcs.xml.dist

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
3131
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
3232
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
33-
<rule ref="Generic.Commenting.Todo"/>
33+
<!-- rule ref="Generic.Commenting.Todo"/ -->
3434
<rule ref="Generic.Files.ByteOrderMark"/>
3535
<rule ref="Generic.Files.EndFileNewline"/>
3636
<rule ref="Generic.Files.InlineHTML"/>
@@ -196,7 +196,6 @@
196196
<exclude name="Squiz.Operators.IncrementDecrementUsage.NoBrackets"/><!-- there is no need for brackets -->
197197
</rule>
198198
<rule ref="Squiz.Operators.ValidLogicalOperators"/>
199-
<rule ref="Squiz.PHP.CommentedOutCode"/>
200199
<rule ref="Squiz.PHP.GlobalKeyword"/>
201200
<rule ref="Squiz.PHP.InnerFunctions"/>
202201
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>

rules.neon

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ services:
106106
arguments:
107107
reportTransitivelyDeadMethodAsSeparateError: %shipmonkDeadCode.reportTransitivelyDeadMethodAsSeparateError%
108108
trackMixedAccess: %shipmonkDeadCode.trackMixedAccess%
109+
debugMembers: %shipmonkDeadCode.debug.usagesOf%
110+
editorUrl: %editorUrl%
109111

110112
-
111113
class: ShipMonk\PHPStan\DeadCode\Compatibility\BackwardCompatibilityChecker
@@ -137,6 +139,8 @@ parameters:
137139
tests:
138140
enabled: false
139141
devPaths: null
142+
debug:
143+
usagesOf: []
140144

141145
parametersSchema:
142146
shipmonkDeadCode: structure([
@@ -172,4 +176,7 @@ parametersSchema:
172176
devPaths: schema(listOf(string()), nullable())
173177
])
174178
])
179+
debug: structure([
180+
usagesOf: listOf(string())
181+
])
175182
])

src/Collector/ConstantFetchCollector.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private function registerFunctionCall(FuncCall $node, Scope $scope): void
125125

126126
$this->registerUsage(
127127
new ClassConstantUsage(
128-
$this->usageOriginDetector->detectOrigin($scope),
128+
$this->usageOriginDetector->detectOrigin($node, $scope),
129129
new ClassConstantRef($className, $constantName, true),
130130
),
131131
$node,
@@ -157,7 +157,7 @@ private function registerFetch(ClassConstFetch $node, Scope $scope): void
157157
foreach ($this->getDeclaringTypesWithConstant($ownerType, $constantName) as $className) {
158158
$this->registerUsage(
159159
new ClassConstantUsage(
160-
$this->usageOriginDetector->detectOrigin($scope),
160+
$this->usageOriginDetector->detectOrigin($node, $scope),
161161
new ClassConstantRef($className, $constantName, $possibleDescendantFetch),
162162
),
163163
$node,

src/Collector/MethodCallCollector.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef;
2626
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage;
2727
use ShipMonk\PHPStan\DeadCode\Graph\CollectedUsage;
28+
use ShipMonk\PHPStan\DeadCode\Graph\UsageOrigin;
2829
use ShipMonk\PHPStan\DeadCode\Graph\UsageOriginDetector;
2930

3031
/**
@@ -133,7 +134,7 @@ private function registerMethodCall(
133134
foreach ($this->getDeclaringTypesWithMethod($methodName, $callerType, TrinaryLogic::createNo(), $possibleDescendantCall) as $methodRef) {
134135
$this->registerUsage(
135136
new ClassMethodUsage(
136-
$this->usageOriginDetector->detectOrigin($scope),
137+
$this->usageOriginDetector->detectOrigin($methodCall, $scope),
137138
$methodRef,
138139
),
139140
$methodCall,
@@ -163,7 +164,7 @@ private function registerStaticCall(
163164
foreach ($this->getDeclaringTypesWithMethod($methodName, $callerType, TrinaryLogic::createYes(), $possibleDescendantCall) as $methodRef) {
164165
$this->registerUsage(
165166
new ClassMethodUsage(
166-
$this->usageOriginDetector->detectOrigin($scope),
167+
$this->usageOriginDetector->detectOrigin($staticCall, $scope),
167168
$methodRef,
168169
),
169170
$staticCall,
@@ -189,7 +190,7 @@ private function registerArrayCallable(
189190
foreach ($this->getDeclaringTypesWithMethod($methodName, $caller, TrinaryLogic::createMaybe()) as $methodRef) {
190191
$this->registerUsage(
191192
new ClassMethodUsage(
192-
$this->usageOriginDetector->detectOrigin($scope),
193+
$this->usageOriginDetector->detectOrigin($array, $scope),
193194
$methodRef,
194195
),
195196
$array,
@@ -205,7 +206,7 @@ private function registerAttribute(Attribute $node, Scope $scope): void
205206
{
206207
$this->registerUsage(
207208
new ClassMethodUsage(
208-
null,
209+
UsageOrigin::fromScope($node, $scope),
209210
new ClassMethodRef($scope->resolveName($node->name), '__construct', false),
210211
),
211212
$node,
@@ -221,7 +222,7 @@ private function registerClone(Clone_ $node, Scope $scope): void
221222
foreach ($this->getDeclaringTypesWithMethod($methodName, $callerType, TrinaryLogic::createNo()) as $methodRef) {
222223
$this->registerUsage(
223224
new ClassMethodUsage(
224-
$this->usageOriginDetector->detectOrigin($scope),
225+
$this->usageOriginDetector->detectOrigin($node, $scope),
225226
$methodRef,
226227
),
227228
$node,

src/Collector/ProvidedUsagesCollector.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ private function validateUsage(
8686
$memberRef = $usage->getMemberRef();
8787
$memberRefClass = $memberRef->getClassName();
8888

89-
$originRef = $usage->getOrigin();
90-
$originRefClass = $originRef === null ? null : $originRef->getClassName();
89+
$origin = $usage->getOrigin();
90+
$originClass = $origin->getClassName();
91+
$originMethod = $origin->getMethodName();
9192

9293
$context = sprintf(
93-
"It was emitted as %s by %s for node '%s' in '%s' on line %s",
94-
$usage->toHumanString(),
94+
"It emitted usage of %s by %s for node '%s' in '%s' on line %s",
95+
$usage->getMemberRef()->toHumanString(),
9596
get_class($provider),
9697
get_class($node),
9798
$scope->getFile(),
@@ -102,16 +103,13 @@ private function validateUsage(
102103
throw new LogicException("Class '$memberRefClass' does not exist. $context");
103104
}
104105

105-
if (
106-
$originRef !== null
107-
&& $originRefClass !== null
108-
) {
109-
if (!$this->reflectionProvider->hasClass($originRefClass)) {
110-
throw new LogicException("Class '{$originRefClass}' does not exist. $context");
106+
if ($originClass !== null) {
107+
if (!$this->reflectionProvider->hasClass($originClass)) {
108+
throw new LogicException("Class '{$originClass}' does not exist. $context");
111109
}
112110

113-
if (!$this->reflectionProvider->getClass($originRefClass)->hasMethod($originRef->getMemberName())) {
114-
throw new LogicException("Method '{$originRef->getMemberName()}' does not exist in class '$originRefClass'. $context");
111+
if ($originMethod !== null && !$this->reflectionProvider->getClass($originClass)->hasMethod($originMethod)) {
112+
throw new LogicException("Method '{$originMethod}' does not exist in class '$originClass'. $context");
115113
}
116114
}
117115
}

src/Enum/NeverReportedReason.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace ShipMonk\PHPStan\DeadCode\Enum;
4+
5+
interface NeverReportedReason
6+
{
7+
8+
public const ABSTRACT_TRAIT_METHOD = 'abstract trait method';
9+
public const PRIVATE_CONSTRUCTOR_NO_PARAMS = 'private constructor without params';
10+
public const UNSUPPORTED_MAGIC_METHOD = 'unsupported magic method';
11+
12+
}

src/Graph/ClassConstantUsage.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ final class ClassConstantUsage extends ClassMemberUsage
1414
private ClassConstantRef $fetch;
1515

1616
/**
17-
* @param ClassMethodRef|null $origin The method where the call occurs
17+
* @param UsageOrigin $origin The method where the fetch occurs
1818
* @param ClassConstantRef $fetch The fetch of the constant
1919
*/
2020
public function __construct(
21-
?ClassMethodRef $origin,
21+
UsageOrigin $origin,
2222
ClassConstantRef $fetch
2323
)
2424
{

src/Graph/ClassMemberUsage.php

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace ShipMonk\PHPStan\DeadCode\Graph;
44

5-
use LogicException;
65
use ShipMonk\PHPStan\DeadCode\Enum\MemberType;
76

87
/**
@@ -14,25 +13,15 @@ abstract class ClassMemberUsage
1413
/**
1514
* Origin method of the usage, "where it was called from"
1615
* This is required for proper transitive dead code detection.
17-
*
18-
* @see UsageOriginDetector for typical usage
1916
*/
20-
private ?ClassMethodRef $origin;
17+
private UsageOrigin $origin;
2118

22-
public function __construct(?ClassMethodRef $origin)
19+
public function __construct(UsageOrigin $origin)
2320
{
24-
if ($origin !== null && $origin->isPossibleDescendant()) {
25-
throw new LogicException('Origin should always be exact place in codebase.');
26-
}
27-
28-
if ($origin !== null && $origin->getClassName() === null) {
29-
throw new LogicException('Origin should always be exact place in codebase, thus className should be known.');
30-
}
31-
3221
$this->origin = $origin;
3322
}
3423

35-
public function getOrigin(): ?ClassMethodRef
24+
public function getOrigin(): UsageOrigin
3625
{
3726
return $this->origin;
3827
}
@@ -49,12 +38,4 @@ abstract public function getMemberRef(): ClassMemberRef;
4938
*/
5039
abstract public function concretizeMixedUsage(string $className): self;
5140

52-
public function toHumanString(): string
53-
{
54-
$origin = $this->origin !== null ? $this->origin->toHumanString() : 'unknown';
55-
$callee = $this->getMemberRef()->toHumanString();
56-
57-
return "$origin -> $callee";
58-
}
59-
6041
}

src/Graph/ClassMethodUsage.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ final class ClassMethodUsage extends ClassMemberUsage
1414
private ClassMethodRef $callee;
1515

1616
/**
17-
* @param ClassMethodRef|null $origin The method where the call occurs
17+
* @param UsageOrigin $origin The method where the call occurs
1818
* @param ClassMethodRef $callee The method being called
1919
*/
2020
public function __construct(
21-
?ClassMethodRef $origin,
21+
UsageOrigin $origin,
2222
ClassMethodRef $callee
2323
)
2424
{

src/Graph/CollectedUsage.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ public function serialize(): string
6060
$data = [
6161
'e' => $this->excludedBy,
6262
't' => $this->usage->getMemberType(),
63-
'o' => $origin === null
64-
? null
65-
: [
63+
'o' => [
6664
'c' => $origin->getClassName(),
67-
'm' => $origin->getMemberName(),
68-
'd' => $origin->isPossibleDescendant(),
65+
'm' => $origin->getMethodName(),
66+
'f' => $origin->getFile(),
67+
'l' => $origin->getLine(),
68+
'r' => $origin->getReason(),
6969
],
7070
'm' => [
7171
'c' => $memberRef->getClassName(),
@@ -84,14 +84,14 @@ public function serialize(): string
8484
public static function deserialize(string $data): self
8585
{
8686
try {
87-
/** @var array{e: string|null, t: MemberType::*, o: array{c: string|null, m: string, d: bool}|null, m: array{c: string|null, m: string, d: bool}} $result */
87+
/** @var array{e: string|null, t: MemberType::*, o: array{c: string|null, m: string|null, f: string|null, l: int|null, r: string|null}, m: array{c: string|null, m: string, d: bool}} $result */
8888
$result = json_decode($data, true, 3, JSON_THROW_ON_ERROR);
8989
} catch (JsonException $e) {
9090
throw new LogicException('Deserialization failure: ' . $e->getMessage(), 0, $e);
9191
}
9292

9393
$memberType = $result['t'];
94-
$origin = $result['o'] === null ? null : new ClassMethodRef($result['o']['c'], $result['o']['m'], $result['o']['d']);
94+
$origin = new UsageOrigin($result['o']['c'], $result['o']['m'], $result['o']['f'], $result['o']['l'], $result['o']['r']);
9595
$exclusionReason = $result['e'];
9696

9797
$usage = $memberType === MemberType::CONSTANT

0 commit comments

Comments
 (0)