Skip to content

Commit 177f344

Browse files
authored
Detect callables invoked via register_shutdown_function (#139)
1 parent c82b690 commit 177f344

File tree

7 files changed

+27
-11
lines changed

7 files changed

+27
-11
lines changed

config/extension.neon

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ services:
9898
- phpstan.collector
9999

100100
-
101-
class: TomasVotruba\UnusedPublic\Collectors\Callable_\CallUserFuncCollector
101+
class: TomasVotruba\UnusedPublic\Collectors\Callable_\CallbackFunctionCollector
102102
tags:
103103
- phpstan.collector
104104

src/Collectors/Callable_/CallUserFuncCollector.php renamed to src/Collectors/Callable_/CallbackFunctionCollector.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
/**
1818
* @implements Collector<FuncCall, non-empty-array<string>|null>
1919
*/
20-
final readonly class CallUserFuncCollector implements Collector
20+
final readonly class CallbackFunctionCollector implements Collector
2121
{
2222
public function __construct(
2323
private Configuration $configuration,
@@ -92,6 +92,10 @@ private function shouldSkipNode(Node $node): bool
9292
return true;
9393
}
9494

95-
return strtolower($node->name->toString()) !== 'call_user_func';
95+
return !in_array(
96+
strtolower($node->name->toString()),
97+
['call_user_func', 'register_shutdown_function'],
98+
true
99+
);
96100
}
97101
}

src/NodeCollectorExtractor.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use PHPStan\Node\CollectedDataNode;
88
use TomasVotruba\UnusedPublic\CollectorMapper\MethodCallCollectorMapper;
99
use TomasVotruba\UnusedPublic\Collectors\Callable_\AttributeCallableCollector;
10-
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallUserFuncCollector;
10+
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallbackFunctionCollector;
1111
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallableCollector;
1212
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallCollector;
1313
use TomasVotruba\UnusedPublic\Collectors\StaticCall\StaticMethodCallableCollector;
@@ -48,7 +48,7 @@ private function extractCollectedDatas(CollectedDataNode $collectedDataNode): ar
4848
$collectedDataNode->get(StaticMethodCallCollector::class),
4949
$collectedDataNode->get(StaticMethodCallableCollector::class),
5050
$collectedDataNode->get(AttributeCallableCollector::class),
51-
$collectedDataNode->get(CallUserFuncCollector::class),
51+
$collectedDataNode->get(CallbackFunctionCollector::class),
5252
];
5353
}
5454
}

tests/Rules/LocalOnlyPublicClassMethodRule/LocalOnlyPublicClassMethodRuleTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use PHPStan\Testing\RuleTestCase;
1111
use PHPUnit\Framework\Attributes\DataProvider;
1212
use TomasVotruba\UnusedPublic\Collectors\Callable_\AttributeCallableCollector;
13-
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallUserFuncCollector;
13+
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallbackFunctionCollector;
1414
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallCollector;
1515
use TomasVotruba\UnusedPublic\Collectors\PublicClassMethodCollector;
1616
use TomasVotruba\UnusedPublic\Collectors\StaticCall\StaticMethodCallCollector;
@@ -80,7 +80,7 @@ protected function getCollectors(): array
8080
self::getContainer()->getByType(MethodCallCollector::class),
8181
self::getContainer()->getByType(StaticMethodCallCollector::class),
8282
self::getContainer()->getByType(AttributeCallableCollector::class),
83-
self::getContainer()->getByType(CallUserFuncCollector::class),
83+
self::getContainer()->getByType(CallbackFunctionCollector::class),
8484
];
8585
}
8686

tests/Rules/RelativeUnusedPublicClassMethodRule/RelativeUnusedPublicClassMethodRuleTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use PHPStan\Testing\RuleTestCase;
1111
use PHPUnit\Framework\Attributes\DataProvider;
1212
use TomasVotruba\UnusedPublic\Collectors\Callable_\AttributeCallableCollector;
13-
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallUserFuncCollector;
13+
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallbackFunctionCollector;
1414
use TomasVotruba\UnusedPublic\Collectors\FormTypeClassCollector;
1515
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallableCollector;
1616
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallCollector;
@@ -64,7 +64,7 @@ protected function getCollectors(): array
6464
// callables
6565
self::getContainer()->getByType(StaticMethodCallableCollector::class),
6666
self::getContainer()->getByType(AttributeCallableCollector::class),
67-
self::getContainer()->getByType(CallUserFuncCollector::class),
67+
self::getContainer()->getByType(CallbackFunctionCollector::class),
6868
];
6969
}
7070

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TomasVotruba\UnusedPublic\Tests\Rules\UnusedPublicClassMethodRule\Fixture;
6+
7+
/**
8+
* @var \TomasVotruba\UnusedPublic\Tests\Rules\UnusedPublicClassMethodRule\Source\Caller1 $caller1
9+
*/
10+
11+
register_shutdown_function([$caller1, 'callIt']);

tests/Rules/UnusedPublicClassMethodRule/UnusedPublicClassMethodRuleTest.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use PHPStan\Testing\RuleTestCase;
1111
use PHPUnit\Framework\Attributes\DataProvider;
1212
use TomasVotruba\UnusedPublic\Collectors\Callable_\AttributeCallableCollector;
13-
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallUserFuncCollector;
13+
use TomasVotruba\UnusedPublic\Collectors\Callable_\CallbackFunctionCollector;
1414
use TomasVotruba\UnusedPublic\Collectors\FormTypeClassCollector;
1515
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallableCollector;
1616
use TomasVotruba\UnusedPublic\Collectors\MethodCall\MethodCallCollector;
@@ -174,6 +174,7 @@ public static function provideData(): Iterator
174174

175175
yield [[__DIR__ . '/Fixture/plain.php', __DIR__ . '/Source/Caller1.php'], []];
176176
yield [[__DIR__ . '/Fixture/plain-call-user-func.php', __DIR__ . '/Source/Caller1.php'], []];
177+
yield [[__DIR__ . '/Fixture/plain-call-shutdown-function.php', __DIR__ . '/Source/Caller1.php'], []];
177178
yield [[__DIR__ . '/Fixture/SkipCrashBug89.php.inc'], []];
178179

179180
yield [[__DIR__ . '/Fixture/SkipJsonSerialize.php'], []];
@@ -203,7 +204,7 @@ protected function getCollectors(): array
203204
// callables
204205
self::getContainer()->getByType(StaticMethodCallableCollector::class),
205206
self::getContainer()->getByType(AttributeCallableCollector::class),
206-
self::getContainer()->getByType(CallUserFuncCollector::class),
207+
self::getContainer()->getByType(CallbackFunctionCollector::class),
207208
];
208209
}
209210

0 commit comments

Comments
 (0)