bmewburn / vscode-intelephense

PHP intellisense for Visual Studio Code
https://intelephense.com
Other
1.61k stars 94 forks source link

Support `@use` for use with templates / generics when placed above use declaration #2796

Closed KorvinSzanto closed 6 months ago

KorvinSzanto commented 7 months ago

Feature description @use allows a developer to define the type of a used trait. This is particularly helpful when using a trait that has generic types. For example:

If I have this trait:

/**
 * @template T of mixed
 */
trait FooTrait
{
    /** @type T */
    private mixed $value = null;

    /**
     * @param T $value
     */
    public function set(mixed $value): void
    {
        $this->value = $value;
    }

    /**
     * @return T
     */
    public function get(): mixed
    {
        return $this->value;
    }
}

And a class that uses that trait in a way that exposes a new generic template:

/**
 * @template T of mixed
 */
class Foo
{
    /** @use FooTrait<T> */
    use FooTrait;
}

I should be able to specify the type for Foo's ->get and ->set methods when I create new instances. For example:

/** @var Foo<string> $string */
$string = new Foo;
$string->set('test');

/** @var Foo<int> $int */
$int = new Foo;
$int->set(5);

function tryPassing(string $a, int $b): void
{
}

tryPassing($string->get(), $int->get());

However in the current intelliphense version the resolved return type for both $int->get() and $string->get() is mixed.

To further demonstrate the issue here, focus on the ->set methods. The following code is invalid and should be given a red squiggly:

/** @var Foo<int> $int */
$int = new Foo;
$int->set('test'); // Passing a `string` for an `int` argument

In the current version of intelliphense this would be allowed. Compare that with the output of PHPStan: https://phpstan.org/r/ec86e94e-4ac3-4ff0-accb-8e158f891e81

Describe the solution you'd like Trait generics should be supported and @use phpdocs should allow specifying generic types.

Additional context Add any other context or screenshots about the feature request here.

bmewburn commented 7 months ago

It works if you place @use FooTrait<T> in the class docblock. I'll expand it to placements above the use trait declaration.