vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 660 forks source link

False positive UnusedParam for __call and __callStatic methods #11040

Open MauricioFauth opened 3 months ago

MauricioFauth commented 3 months ago

The magic methods __call and __callStatic requires exactly two parameters, otherwise a fatal error will occur.

So, both $name and $arguments are required parameters, even if they are not used inside the method.

<?php declare(strict_types=1);

/**
 * @method string foo()
 * @method static string bar()
 */
final class MethodTest
{
    /** @param mixed[] $arguments */
    public function __call(string $name, array $arguments): mixed
    {
        return match ($name) {
            'foo' => 'foo',
            default => throw new RuntimeException(),
        };
    }

    /** @param mixed[] $arguments */
    public static function __callStatic(string $name, array $arguments): mixed
    {
        return match ($name) {
            'bar' => 'bar',
            default => throw new RuntimeException(),
        };
    }
}

$obj = new MethodTest();
echo $obj->foo();
echo $obj::bar();
echo MethodTest::bar();

https://3v4l.org/3P1cM

foobarbar

https://3v4l.org/H55oa

-     public function __call(string $name, array $arguments): mixed
+     public function __call(string $name): mixed
Fatal error: Method MethodTest::__call() must take exactly 2 arguments in /in/H55oa on line 10

https://3v4l.org/XLoWr

-     public static function __callStatic(string $name, array $arguments): mixed
+     public static function __callStatic(string $name): mixed
Fatal error: Method MethodTest::__callStatic() must take exactly 2 arguments in /in/XLoWr on line 19

https://psalm.dev/r/1c112dae46

psalm-github-bot[bot] commented 3 months ago

I found these snippets:

https://psalm.dev/r/1c112dae46 ```php 'foo', default => throw new RuntimeException(), }; } /** @param mixed[] $arguments */ public static function __callStatic(string $name, array $arguments): mixed { return match ($name) { 'bar' => 'bar', default => throw new RuntimeException(), }; } } $obj = new MethodTest(); echo $obj->foo(); echo $obj::bar(); echo MethodTest::bar(); ``` ``` Psalm output (using commit 16b24bd): INFO: PossiblyUnusedMethod - 19:28 - Cannot find any calls to method MethodTest::__callStatic INFO: UnusedParam - 10:48 - Param #2 is never referenced in this method INFO: UnusedParam - 19:61 - Param #2 is never referenced in this method ```