Skip to content

Commit

Permalink
Support array callbacks like [$this, 'method'] (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
janedbal authored Jul 24, 2024
1 parent 6dbe16f commit dab2fe6
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 18 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class MyEntrypointProvider implements EntrypointProvider

- Only method calls are detected
- Including static methods, trait methods, interface methods, first class callables, etc.
- Callbacks like `[$this, 'method']` are mostly not detected; prefer first class callables `$this->method(...)`
- Any calls on mixed types are not detected, e.g. `$unknownClass->method()`
- Expression method calls are not detected, e.g. `$this->$methodName()`
- Anonymous classes are ignored
Expand Down
24 changes: 7 additions & 17 deletions src/Collector/MethodCallCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use PhpParser\Node;
use PhpParser\Node\Attribute;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\CallLike;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\NullsafeMethodCall;
Expand Down Expand Up @@ -70,8 +70,8 @@ public function processNode(
$this->registerStaticCall($node, $scope);
}

if ($node instanceof FuncCall) {
$this->registerFuncCall($node, $scope);
if ($node instanceof Array_) {
$this->registerArrayCallable($node, $scope);
}

if ($node instanceof Attribute) {
Expand Down Expand Up @@ -153,23 +153,13 @@ private function registerStaticCall(
}
}

private function registerFuncCall(
FuncCall $functionCall,
private function registerArrayCallable(
Array_ $array,
Scope $scope
): void
{
if (!$functionCall->name instanceof Name || $functionCall->name->toString() !== 'array_map') { // we should support all native fns
return;
}

if (!isset($functionCall->getArgs()[0])) {
return;
}

$callableType = $scope->getType($functionCall->getArgs()[0]->value);

if ($callableType->isCallable()->yes()) {
foreach ($callableType->getConstantArrays() as $constantArray) {
if ($scope->getType($array)->isCallable()->yes()) {
foreach ($scope->getType($array)->getConstantArrays() as $constantArray) {
$callableTypeAndNames = $constantArray->findTypeAndMethodNames();

foreach ($callableTypeAndNames as $typeAndName) {
Expand Down
5 changes: 5 additions & 0 deletions tests/Rule/data/DeadMethodRule/array-map-1.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class ArrayMapTest
public function __construct()
{
array_map([$this, 'calledMagically'], ['a']);
array_filter([], [$this, 'calledMagically2']);
[$this, 'calledMagically3'];
}

private function notCalledMagically(string $foo): string // error: Unused DeadMap\ArrayMapTest::notCalledMagically
Expand All @@ -19,6 +21,9 @@ private function calledMagically(string $foo): string
{
return $foo;
}

private function calledMagically2(): void {}
private function calledMagically3(): void {}
}

new ArrayMapTest();

0 comments on commit dab2fe6

Please sign in to comment.