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

Doesn't know the type when iterate iterable

Open momala454 opened this issue 1 year ago • 1 comments

Describe the bug When doing foreach on iterables built in php, intelepehense doesn't know the type. Example DOMNodeList iterates to DOMElement|DOMNode|DOMNameSpaceNode|null

To Reproduce

$dom = new \DOMDocument();
            $xpath = new \DOMXPath($dom);

            $links = $xpath->query('.//a[@href]');
            assert($links !== false);
            foreach ($links as $link) {
                var_dump($link);
                exit;
            }

Expected behavior $link is DOMElement|DOMNode|DOMNameSpaceNode|null

Screenshots image

Platform and version OS and Intelephense version.

momala454 avatar May 30 '24 07:05 momala454

I think the upstream stubs could be improved to solve this https://github.com/JetBrains/phpstorm-stubs/blob/master/dom/dom_c.php#L1340

bmewburn avatar May 30 '24 08:05 bmewburn

I think it's not totally fixed.

DOMNodeList iterates to DOMElement|DOMNode|DOMNameSpaceNode

You only show \DOMNode|\DOMNameSpaceNode

When using query, it looks to be the correct type, but when using DOMDocument::getElementsByTagName which also return a DOMNodeList, PHPStan says the type is DOMElement, but intelephense says only \DOMNode|\DOMNameSpaceNode

$dom = new \DOMDocument();
$xpath = new \DOMXPath($dom);

$links = $xpath->query('.//a[@href]');
assert($links !== false);
foreach ($links as $link) {
    var_dump($link);
}

$links = $dom->getElementsByTagName('a');
assert($links !== false);
foreach ($links as $link) {
    var_dump($link);
}

image

momala454 avatar Aug 13 '24 13:08 momala454

DOMElement extends DOMNode so it is redundant to have a union here. The upstream stubs need further work to make them templated. You're welcome to use phpstan's stubs as a guide and submit a PR to the upstream stubs package.

bmewburn avatar Aug 13 '24 21:08 bmewburn

Except that i'm using DOMElement only method :

if (!$img->hasAttribute('src')) {
                        continue;
                    }

and intelephense shows an error here image

momala454 avatar Aug 13 '24 21:08 momala454

The DOMNodeList class would need a template and then the getElementsByTagName would need to be changed to return DOMNodeList<DOMElement>. It's an upstream issue with the stubs.

bmewburn avatar Aug 13 '24 21:08 bmewburn

This seems similar, and their solution is to first check it's type before calling the property. I tested, and this does indeed seem to work, though it seems a little silly to me that this would be necessary. I guess it's technically correct though, so good enough for me.

JacobDB avatar Aug 23 '24 15:08 JacobDB