phppsalm-php

How do I use Psalm's UnusedMethod Feature?


I'm trying to use the psalm static analysis tool for PHP. It's my understanding that this tool can tell me about unused methods in my codebase. However, if I create a simple test file

#File: src/test.php
<?php
class A {
    private function foo() : void {}
}

new A();

and then run psalm

$ ./vendor/bin/psalm --find-dead-code src/test.php 
Scanning files...
Analyzing files...

------------------------------
No errors found!
------------------------------

Checks took 0.16 seconds and used 32.694MB of memory
Psalm was able to infer types for 100% of the codebase

or psalter,

$ ./vendor/bin/psalter --find-unused-code --dry-run --issues=UnusedMethod src/test.php 
Scanning files...
Analyzing files...

------------------------------
No errors found!
------------------------------

Checks took 0.05 seconds and used 29.214MB of memory
Psalm was able to infer types for 100% of the codebase

no errors are found.

Why isn't psalm finding the unused method foo? Is there extra configuration that's needed? Or do I misunderstand what this tool does? My psalm.xml file is below.

<?xml version="1.0"?>
<psalm
    totallyTyped="false"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://getpsalm.org/schema/config"
    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
    <projectFiles>
        <directory name="src" />
        <ignoreFiles>
            <directory name="vendor" />
        </ignoreFiles>
    </projectFiles>

    <issueHandlers>
        <LessSpecificReturnType errorLevel="info" />

        <!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->

        <DeprecatedMethod errorLevel="info" />
        <DeprecatedProperty errorLevel="info" />
        <DeprecatedClass errorLevel="info" />
        <DeprecatedConstant errorLevel="info" />
        <DeprecatedInterface errorLevel="info" />
        <DeprecatedTrait errorLevel="info" />

        <InternalMethod errorLevel="info" />
        <InternalProperty errorLevel="info" />
        <InternalClass errorLevel="info" />

        <MissingClosureReturnType errorLevel="info" />
        <MissingReturnType errorLevel="info" />
        <MissingPropertyType errorLevel="info" />
        <InvalidDocblock errorLevel="info" />
        <MisplacedRequiredParam errorLevel="info" />

        <PropertyNotSetInConstructor errorLevel="info" />
        <MissingConstructor errorLevel="info" />
        <MissingClosureParamType errorLevel="info" />
        <MissingParamType errorLevel="info" />

        <RedundantCondition errorLevel="info" />

        <DocblockTypeContradiction errorLevel="info" />
        <RedundantConditionGivenDocblockType errorLevel="info" />

        <UnresolvableInclude errorLevel="info" />

        <RawObjectIteration errorLevel="info" />

        <InvalidStringClass errorLevel="info" />

        <UnusedMethod errorLevel="info" />
    </issueHandlers>
</psalm>

Solution

  • Psalm creator here - dead code detection only detects unused classes and methods when the entire project is analysed - e.g. ./vendor/bin/psalm --find-dead-code, omitting src/test.php.

    While private methods and properties are a special case (their non-use can be inferred without checking the entire project), for public/protected methods and properties everything must be consumed.