psalm-plugin-symfony icon indicating copy to clipboard operation
psalm-plugin-symfony copied to clipboard

False positive "UnusedClass" if classes used via their interface

Open shmaltorhbooks opened this issue 3 years ago • 6 comments

Hello.

Given:

Psalm 4.6.2 psalm/symfony-plugin v.2.1.2 Symfony v4.4.*

PHP code:

namespace App;

interface SomeImportantInterface {}

class SomeLogic implements SomeImportantInterface {}

class Handler
{
    public function __invoke(SomeImportantInterface $logic)
    {
    }
}

symfony DI config:

App\SomeImportantInterface:
    class: App\SomeLogic

App\Handler:
    autowire: true

psalm.xml:

    <plugins>
        <pluginClass class="Psalm\SymfonyPsalmPlugin\Plugin">
            <containerXml>var/path/to/xml_dump.xml</containerXml>
        </pluginClass>
    </plugins>

psalm output:

ERROR: UnusedClass - src/App/SomeLogic.php:3:7 - Class App\SomeLogic is never used (see https://psalm.dev/075)
class SomeLogic implements SomeImportantInterface

It would be very helpful to detect this kind of cases and not to mark this classes as Unused.

shmaltorhbooks avatar Mar 01 '21 16:03 shmaltorhbooks

See also https://github.com/vimeo/psalm/issues/3293

githoober avatar May 06 '21 22:05 githoober

@shmaltorhbooks @githoober could you please confirm that it is fixed with v3.0.0? If not, feel free to reopen the issue.

seferov avatar Aug 22 '21 13:08 seferov

@seferov it's not fixed. I am still getting the same error(s) about unused classes. I am on the latest psalm and the latest plugin versions Psalm 4.10.0@916b098b008f6de4543892b1e0651c1c3b92cbfa and psalm/plugin-symfony v3.0.3 Psalm Plugin for Symfony.

githoober avatar Oct 05 '21 22:10 githoober

@githoober did you configure containerXml? https://github.com/psalm/psalm-plugin-symfony#configuration

seferov avatar Oct 06 '21 01:10 seferov

@seferov Yes, I did configure the container XML file. Here's a sample project that produces the following errors psalm-symfony-test.tar.gz psalm-symfony-plugin-issue-1

githoober avatar Oct 06 '21 12:10 githoober

@githoober thanks for the sample. I will check it

seferov avatar Oct 08 '21 02:10 seferov

I have the same problem in my application (Symfony 6.1). I do not use standard Symfony directory structure, but I do not think that it's a problem. It seems that psalm does not understand Symfony DI. When I instantiate DoctrineConfigRepository class in a regular way (new ConfigRepositorClass...) everything is fine.

I use phpunit-plugin and symfony-plugin.

Example:

services.yml:

services:
  _defaults:
    public: true

  hash_generating.domain.repository.config:
    class: HashGenerating\Infrastructure\Persistence\Doctrine\Repository\DoctrineConfigRepository
    arguments:
      - "@doctrine.orm.entity_manager"

DoctrineConfigRepository:

final class DoctrineConfigRepositoryTest extends KernelTestCase
{
    private ConfigRepository $configRepository;

    protected function setUp(): void
    {
        $kernel = self::bootKernel();
        $container = $kernel->getContainer();

        $this->configRepository = $container->get('hash_generating.domain.repository.config');

        parent::setUp();
    }

    public function testOne(): void
    {
        $config = $this->configRepository->getByValue('last_number');

        $this->assertInstanceOf(Config::class, $config);
    }
}

My config:

<?xml version="1.0"?>
<psalm
    errorLevel="7"
    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"
    cacheDirectory="./data/psalm/cache/"
    findUnusedVariablesAndParams="true"
    ensureArrayStringOffsetsExist="true"
    resolveFromConfigFile="true"
    findUnusedCode="true"
>
    <projectFiles>
        <directory name="./app"/>
        <directory name="./src"/>
        <directory name="./tests"/>
        <ignoreFiles>
            <directory name="./vendor"/>
            <file name="./tests/bootstrap.php"/>
        </ignoreFiles>
    </projectFiles>

    <plugins>
        <pluginClass class="Psalm\SymfonyPsalmPlugin\Plugin">
            <containerXml>var/cache/test/App_KernelTestDebugContainer.xml</containerXml>
        </pluginClass>
        <pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
    </plugins>

    <issueHandlers>
        <UnusedClass>
            <errorLevel type="suppress">
                <directory name="src/HashGenerating/Infrastructure/Persistence/Doctrine/Type"/>
            </errorLevel>
        </UnusedClass>
    </issueHandlers>
</psalm>

Any ideas ??

c3zi avatar Dec 02 '22 17:12 c3zi

Same here - latest psalm + the plugin, symfony lts 5.4: all autoloaded code (including controllers) is marked as UnusedClass.

zerkms avatar Mar 24 '23 04:03 zerkms

Same here, latest psalm, symfony 6.2, php 8.2

andrei-dascalu avatar Jun 28 '23 06:06 andrei-dascalu

The issue is fixed with v5.0.4. Feel free to reopen the issue if it is not resolved

seferov avatar Nov 10 '23 07:11 seferov

@seferov Hi, still not working for me.

PHP: 8.1.16 vimeo/psalm: 5.15.0 psalm/plugin-symfony: v5.04 symfony/framework-bundle: v5.4.31

psalm.xml:

<?xml version="1.0"?>
<psalm
    errorLevel="4"
    resolveFromConfigFile="true"
    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"
    findUnusedBaselineEntry="true"
    findUnusedCode="true"
>
    <projectFiles>
        <directory name="src"/>
        <ignoreFiles>
            <directory name="vendor"/>
        </ignoreFiles>
    </projectFiles>
    <plugins>
        <pluginClass class="Psalm\SymfonyPsalmPlugin\Plugin">
            <containerXml>var/cache/dev/App_KernelDevDebugContainer.xml</containerXml>
        </pluginClass>
    </plugins>
</psalm>

var/cache/dev/App_KernelDevDebugContainer.xml:

<service id="App\Client\RedisClient" class="App\Client\RedisClient" autowire="true" autoconfigure="true">
...
<service id="App\Repository\SomeRepo" class="App\Repository\SomeRepo" autowire="true" autoconfigure="true">
      <argument type="service" id="App\Repository\OtherRepo"/>
      <argument type="service" id="App\Client\RedisClient"/>

vendor/bin/psalm --debug

Process plugin adjustments...
Loading plugin Psalm\SymfonyPsalmPlugin\Plugin via require
Loaded plugin Psalm\SymfonyPsalmPlugin\Plugin
Target PHP version: 8.1 (inferred from composer.json) Enabled extensions: pdo.
Scanning files...
0 changed files: 
    
Analyzing files...
Checking class references

ERROR: PossiblyUnusedMethod - src/Client/RedisClient.php:21:21 - Cannot find any calls to method App\Client\RedisClient::__construct (see https://psalm.dev/087)
    public function __construct(

plejzner avatar Nov 12 '23 01:11 plejzner

Hello @plejzner, thanks for the detailed report. The original issue was about UnusedClass false positive. However, you are right, also there should not be PossiblyUsusedMethod issue for constructors. It was fixed with v5.0.5

seferov avatar Nov 12 '23 09:11 seferov