diff --git a/README.md b/README.md index 39fbdb6..381e8ba 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ class UserFacade ```neon parameters: shipmonkDeadCode: - trackCallsOnMixed: false + trackMixedAccess: false ``` - If you want to check how many of those cases are present in your codebase, you can run PHPStan analysis with `-vvv` and you will see some diagnostics: diff --git a/rules.neon b/rules.neon index c437732..57c1aa2 100644 --- a/rules.neon +++ b/rules.neon @@ -54,16 +54,20 @@ services: tags: - phpstan.collector arguments: - trackCallsOnMixed: %shipmonkDeadCode.trackCallsOnMixed% + trackMixedAccess: %shipmonkDeadCode.trackMixedAccess% - - class: ShipMonk\PHPStan\DeadCode\Collector\ClassDefinitionCollector + class: ShipMonk\PHPStan\DeadCode\Collector\ConstantFetchCollector tags: - phpstan.collector + arguments: + trackMixedAccess: %shipmonkDeadCode.trackMixedAccess% + - - class: ShipMonk\PHPStan\DeadCode\Collector\ConstantFetchCollector + class: ShipMonk\PHPStan\DeadCode\Collector\ClassDefinitionCollector tags: - phpstan.collector + - class: ShipMonk\PHPStan\DeadCode\Collector\EntrypointCollector tags: @@ -78,12 +82,12 @@ services: - phpstan.diagnoseExtension arguments: reportTransitivelyDeadMethodAsSeparateError: %shipmonkDeadCode.reportTransitivelyDeadMethodAsSeparateError% - trackCallsOnMixed: %shipmonkDeadCode.trackCallsOnMixed% + trackMixedAccess: %shipmonkDeadCode.trackMixedAccess% parameters: shipmonkDeadCode: - trackCallsOnMixed: true + trackMixedAccess: true reportTransitivelyDeadMethodAsSeparateError: false entrypoints: vendor: @@ -101,7 +105,7 @@ parameters: parametersSchema: shipmonkDeadCode: structure([ - trackCallsOnMixed: bool() + trackMixedAccess: bool() reportTransitivelyDeadMethodAsSeparateError: bool() entrypoints: structure([ vendor: structure([ diff --git a/src/Collector/ConstantFetchCollector.php b/src/Collector/ConstantFetchCollector.php index 9d0569f..b298049 100644 --- a/src/Collector/ConstantFetchCollector.php +++ b/src/Collector/ConstantFetchCollector.php @@ -38,9 +38,15 @@ class ConstantFetchCollector implements Collector private ReflectionProvider $reflectionProvider; - public function __construct(ReflectionProvider $reflectionProvider) + private bool $trackMixedAccess; + + public function __construct( + ReflectionProvider $reflectionProvider, + bool $trackMixedAccess + ) { $this->reflectionProvider = $reflectionProvider; + $this->trackMixedAccess = $trackMixedAccess; } public function getNodeType(): string @@ -173,7 +179,7 @@ private function getDeclaringTypesWithConstant( } } - if ($result === []) { // TODO trackFetchesOnMixed + if ($this->trackMixedAccess && $result === []) { $result[] = null; // call over unknown type } diff --git a/src/Collector/MethodCallCollector.php b/src/Collector/MethodCallCollector.php index 45f5e84..bd70572 100644 --- a/src/Collector/MethodCallCollector.php +++ b/src/Collector/MethodCallCollector.php @@ -38,11 +38,11 @@ class MethodCallCollector implements Collector */ private array $callsBuffer = []; - private bool $trackCallsOnMixed; + private bool $trackMixedAccess; - public function __construct(bool $trackCallsOnMixed) + public function __construct(bool $trackMixedAccess) { - $this->trackCallsOnMixed = $trackCallsOnMixed; + $this->trackMixedAccess = $trackMixedAccess; } public function getNodeType(): string @@ -261,7 +261,7 @@ private function getDeclaringTypesWithMethod( } } - if ($this->trackCallsOnMixed) { + if ($this->trackMixedAccess) { $canBeObjectCall = !$typeNoNull->isObject()->no() && !$isStaticCall->yes(); $canBeClassStringCall = !$typeNoNull->isClassString()->no() && !$isStaticCall->no(); diff --git a/src/Rule/DeadCodeRule.php b/src/Rule/DeadCodeRule.php index 3f333e3..4750562 100644 --- a/src/Rule/DeadCodeRule.php +++ b/src/Rule/DeadCodeRule.php @@ -89,7 +89,7 @@ class DeadCodeRule implements Rule, DiagnoseExtension private bool $reportTransitivelyDeadAsSeparateError; - private bool $trackCallsOnMixed; + private bool $trackMixedAccess; /** * memberKey => DeadMember @@ -113,12 +113,12 @@ class DeadCodeRule implements Rule, DiagnoseExtension public function __construct( ClassHierarchy $classHierarchy, bool $reportTransitivelyDeadMethodAsSeparateError, - bool $trackCallsOnMixed + bool $trackMixedAccess ) { $this->classHierarchy = $classHierarchy; $this->reportTransitivelyDeadAsSeparateError = $reportTransitivelyDeadMethodAsSeparateError; - $this->trackCallsOnMixed = $trackCallsOnMixed; + $this->trackMixedAccess = $trackMixedAccess; } public function getNodeType(): string @@ -622,7 +622,7 @@ private function isNeverReportedAsDead(BlackMember $blackMember): bool public function print(Output $output): void { - if ($this->mixedMemberUses === [] || !$output->isDebug() || !$this->trackCallsOnMixed) { + if ($this->mixedMemberUses === [] || !$output->isDebug() || !$this->trackMixedAccess) { return; } diff --git a/tests/Rule/DeadCodeRuleTest.php b/tests/Rule/DeadCodeRuleTest.php index 0b2a63b..780e31f 100644 --- a/tests/Rule/DeadCodeRuleTest.php +++ b/tests/Rule/DeadCodeRuleTest.php @@ -41,7 +41,7 @@ class DeadCodeRuleTest extends RuleTestCase { - private bool $trackMixedCalls = true; + private bool $trackMixedAccess = true; private bool $emitErrorsInGroups = true; @@ -70,8 +70,8 @@ protected function getCollectors(): array return [ new EntrypointCollector($this->getEntrypointProviders()), new ClassDefinitionCollector(), - new MethodCallCollector($this->trackMixedCalls), - new ConstantFetchCollector(self::createReflectionProvider()), + new MethodCallCollector($this->trackMixedAccess), + new ConstantFetchCollector(self::createReflectionProvider(), $this->trackMixedAccess), ]; } @@ -109,12 +109,14 @@ private function doTestDead($files, ?int $lowestPhpVersion = null): void public function testMixedCallsTracked(): void { $this->analyseFiles([__DIR__ . '/data/methods/mixed/tracked.php']); + $this->analyseFiles([__DIR__ . '/data/constants/mixed/tracked.php']); } public function testMixedCallsNotTracked(): void { - $this->trackMixedCalls = false; + $this->trackMixedAccess = false; $this->analyseFiles([__DIR__ . '/data/methods/mixed/untracked.php']); + $this->analyseFiles([__DIR__ . '/data/constants/mixed/untracked.php']); } public function testDiagnoseMixedCalls(): void @@ -320,7 +322,7 @@ public static function provideFiles(): iterable yield 'const-function' => [__DIR__ . '/data/constants/constant-function.php']; yield 'const-dynamic' => [__DIR__ . '/data/constants/dynamic.php']; yield 'const-expr' => [__DIR__ . '/data/constants/expr.php']; - yield 'const-mixed' => [__DIR__ . '/data/constants/mixed.php']; + yield 'const-mixed' => [__DIR__ . '/data/constants/mixed/tracked.php']; yield 'const-override' => [__DIR__ . '/data/constants/override.php']; yield 'const-static' => [__DIR__ . '/data/constants/static.php']; yield 'const-traits-1' => [__DIR__ . '/data/constants/traits-1.php']; diff --git a/tests/Rule/data/constants/mixed.php b/tests/Rule/data/constants/mixed/tracked.php similarity index 92% rename from tests/Rule/data/constants/mixed.php rename to tests/Rule/data/constants/mixed/tracked.php index ef11e2d..ee93e17 100644 --- a/tests/Rule/data/constants/mixed.php +++ b/tests/Rule/data/constants/mixed/tracked.php @@ -56,10 +56,7 @@ function __construct($mixed, string $notClass, object $object, IFace $iface, int function testMethodExists(Iface $iface) { - if (method_exists($iface, 'someMethod')) { - echo $iface::SOME_CONST; // does not not mark Clazz - } - + echo $iface::SOME_CONST; // does not not mark Clazz echo $iface::CONST6; // not defined on Iface, but should mark used on its implementations but not on unrelated Clazz } } diff --git a/tests/Rule/data/constants/mixed/untracked.php b/tests/Rule/data/constants/mixed/untracked.php new file mode 100644 index 0000000..1a0c234 --- /dev/null +++ b/tests/Rule/data/constants/mixed/untracked.php @@ -0,0 +1,64 @@ +testMethodExists(); + } + + function testMethodExists(Iface $iface) + { + echo $iface::SOME_CONST; // does not not mark Clazz + echo $iface::CONST6; // not defined on Iface, but should mark used on its implementations but not on unrelated Clazz + } +} + +new Tester();