PHP code example of shipmonk / dead-code-detector

1. Go to this page and download the library: Download shipmonk/dead-code-detector library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

shipmonk / dead-code-detector example snippets



use ReflectionMethod;
use ShipMonk\PHPStan\DeadCode\Provider\VirtualUsageData;
use ShipMonk\PHPStan\DeadCode\Provider\ReflectionBasedMemberUsageProvider;

class FuzzyTwigUsageProvider extends ReflectionBasedMemberUsageProvider
{

    public function shouldMarkMethodAsUsed(ReflectionMethod $method): ?VirtualUsageData
    {
        if ($method->getDeclaringClass()->implementsInterface(UsedInTwigMarkerInterface::class)) {
            return VirtualUsageData::withNote('Probably used in twig');
        }
        return null;
    }

}

function test(SerializerInterface $serializer): User {
    return $serializer->deserialize('{"name": "John"}', User::class, 'json');
}

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use ReflectionMethod;
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef;
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage;
use ShipMonk\PHPStan\DeadCode\Graph\UsageOrigin;
use ShipMonk\PHPStan\DeadCode\Provider\MemberUsageProvider;
use Symfony\Component\Serializer\SerializerInterface;

class DeserializationUsageProvider implements MemberUsageProvider
{

    public function __construct(
        private UsageOriginDetector $originDetector,
    ) {}

    /**
     * @return list<ClassMemberUsage>
     */
    public function getUsages(Node $node, Scope $scope): array
    {
        if (!$node instanceof MethodCall) {
            return [];
        }

        if (
            // our deserialization calls constructor
            $scope->getType($node->var)->getObjectClassNames() === [SerializerInterface::class] &&
            $node->name->toString() === 'deserialize'
        ) {
            $secondArgument = $node->getArgs()[1]->value;
            $serializedClass = $scope->getType($secondArgument)->getConstantStrings()[0];

            // record the place it was called from (needed for proper transitive dead code elimination)
            $usageOrigin = UsageOrigin::createRegular($node, $scope);

            // record the hidden constructor call
            $constructorRef = new ClassMethodRef($serializedClass->getValue(), '__construct', false);

            return [new ClassMethodUsage($usageOrigin, $constructorRef)];
        }

        return [];
    }

}


use ShipMonk\PHPStan\DeadCode\Excluder\MemberUsageExcluder;

class MyUsageExcluder implements MemberUsageExcluder
{

    public function shouldExclude(ClassMemberUsage $usage, Node $node, Scope $scope): bool
    {
        // ...
    }

}

/** @var ReflectionClass<Foo> $reflection */
$methods = $reflection->getMethods(); // all Foo methods are used here

use ShipMonk\PHPStan\DeadCode\Provider\VirtualUsageData;
use ShipMonk\PHPStan\DeadCode\Provider\ReflectionBasedMemberUsageProvider;

class IgnoreDeadInterfaceUsageProvider extends ReflectionBasedMemberUsageProvider
{
    public function shouldMarkMethodAsUsed(ReflectionMethod $method): ?VirtualUsageData
    {
        if ($method->getDeclaringClass()->isInterface()) {
            return VirtualUsageData::withNote('Interface method, kept for unification even when possibly unused');
        }

        return null;
    }
}
txt
 • Removed method UserFacade::deadMethod
   ! Excluded usage at tests/User/UserFacadeTest.php:241 left intact