vscode-intelephense icon indicating copy to clipboard operation
vscode-intelephense copied to clipboard

Support psalm typedefs

Open palansher opened this issue 2 years ago • 8 comments

Describe the bug I marked it as a bug because in this case, Intelephense does not ignore psalm annotation, and at the same time, shows error.

  1. psalm-type "DriverBaseLinkArrayType" declared
  2. psalm-type "DriverBaseLinkArrayType" applied to variable
  3. Intelephense shows error on using this variable in array_key_exists function

image

image

Expected behavior If Intelephense does not work with psalm annotations, so I suppose it must ignore @psalm-type and @psalm-var annotations. If Intelephense treats them properly, it is much better :) In both cases, I don't expect error messages.

Maybe I am wrong.

PS: PSALM and phpstan do not warn on this syntax Also no possibility to suppress any Intelephense message using style a-la @psalm-suppress. And I did not find a possibility to disable array related checks in settings

Platform and version OS: Ubuntu, Intelephense version: last.

palansher avatar Dec 30 '21 15:12 palansher

It's getting the type from the constructor @param annotation but psalm style typedefs are not supported. I'll leave open as a feature request, but it's unlikely to happen soon. In general, psalm annotations should be prefixed with @psalm- to avoid issues like this.

bmewburn avatar Dec 31 '21 01:12 bmewburn

Thank you! For a while, would you advise if possible to disable this problematic kind of diagnostic instead of disabling diagnostic totally in Intelephence?

palansher avatar Jan 01 '22 14:01 palansher

@palansher you would need to prefix any usage of psalm specific types with @psalm- and provide regular types for unprefixed annotations.

bmewburn avatar Jan 02 '22 03:01 bmewburn

@palansher you would need to prefix any usage of psalm specific types with @psalm- and provide regular types for unprefixed annotations.

Thanks for the advice. But probably I did not get it. I already use psalm-specific types with @psalm- without any success:

image

the code is attached for any case.

PS: Last time I just asked about the possibility to disable specific array checking in Intelephence settings, if one exists.. But disabling inside code of course would be better.

<?php

declare(strict_types=1);

namespace Gt\PaymentToDriver;

use Gt\Error\Exception\DomainException;

/**
 * список подключений учеток водителя к одному или нескольким такси операторам.
 * @psalm-type DriverTopAccountArrayType = array<int,DriverTopAccountLink>
 */
class DriverTopAccountLinkCollection
{
    /**
     * массив с id=>объект
     * @psalm-var DriverTopAccountArrayType
     * @psalm-suppress PropertyNotSetInConstructor
     * @psalm-type DriverTopAccountArrayType
     */
    private $driverTopAccountLinks=[];

    /**
     * @param ?DriverTopAccountArrayType $driverTopAccountLinks
     */
    public function __construct($driverTopAccountLinks = null)
    {
        if ($driverTopAccountLinks) {
            $this->driverTopAccountLinks = $driverTopAccountLinks;
        }
    }

    /** Добавляет элемент в коллекцию */
    public function add(DriverTopAccountLink $driverTopAccountLink): void
    {
        $id = $driverTopAccountLink->getId();
        if (array_key_exists($id, $this->driverTopAccountLinks)) {
            throw new DomainException("В коллекции учеток водителя {$driverTopAccountLink->getDriver()->getId()} 
                уже есть запись с id подключения={$id} для такси оператора {$driverTopAccountLink->getOperator()->getName()}");
        }
        $this->driverTopAccountLinks[$id]=$driverTopAccountLink;
    }

    /**
     * Возвращает массив подключений вместо объекта.
     * @return DriverTopAccountArrayType
     */
    public function getArray()
    {
        return $this->driverTopAccountLinks;
    }

    /** Ищет по ID подключение учетки водителя к такси оператору  */
    public function find(int $id): ?DriverTopAccountLink
    {
        if (!array_key_exists($id, $this->driverTopAccountLinks)) {
            return null;
        }

        return $this->driverTopAccountLinks[$id];
    }

    /** Возвращает по ID подключение учетки водителя к такси оператору  */
    public function get(int $id): DriverTopAccountLink
    {
        if (!$result = $this->find($id)) {
            throw new DomainException("В коллекции подключений учеток водителя нет записи с id={$id}");
        }
        return $result;
    }
}

palansher avatar Jan 02 '22 09:01 palansher

This type is not a real type. It's a psalm typedef

/**
     * @param ?DriverTopAccountArrayType $driverTopAccountLinks
     */
    public function __construct($driverTopAccountLinks = null)
    {
        if ($driverTopAccountLinks) {
            $this->driverTopAccountLinks = $driverTopAccountLinks;
        }
    }

bmewburn avatar Jan 02 '22 11:01 bmewburn

Finally I got it. I need to add extra native PHP type definition (array):

/** @psalm-var DriverTopAccountArrayType */ private array $driverTopAccountLinks=[];

Thank you!

palansher avatar Jan 02 '22 11:01 palansher

I'm very interested in this as well. Is there any other way to declare a typedef so intelephense is aware of it?

rzvc avatar Apr 21 '22 09:04 rzvc

It's worth noting that PHPStan has local type aliases which work pretty much identically to the equivalent in Psalm. Presumably, adding support for one would make it easy to support the other as well.

ZebulanStanphill avatar May 18 '22 01:05 ZebulanStanphill

Finally I got it. I need to add extra native PHP type definition (array):

/** @psalm-var DriverTopAccountArrayType */ private array $driverTopAccountLinks=[];

Thank you!

this trick is still worked in your environment? In my, it not worked, psalm- not recognized. do you install additional plugins/configuration?

VSCode 1.87.2 PHP Intelephense v1.10.4 PHP 7.4 OS: Windows

what extension suggest to work with custom types + intellisense, i was try phpstan, but it work only on project analyze, not in typing

ezyuzin avatar Apr 05 '24 06:04 ezyuzin