派生类返回值的 PhpStorm 类型提示

Posted

技术标签:

【中文标题】派生类返回值的 PhpStorm 类型提示【英文标题】:PhpStorm type hinting for derived class return value 【发布时间】:2014-08-29 01:00:32 【问题描述】:

是否可以提示 phpStorm 在下面的代码中 item() 方法的返回值具有 DOMElement 类型(不修改实际的 PHP 语句,即通过 PhpStorm 的一些外部设置或插件或使用某种 PHPDoc 注释等)?

再次,请不要建议我修改代码中的语句,尤其是 $list->item(0)->getAttribute('test') 部分。

另外,我发现了一个有点相似的问题 PhpStorm type-hinting for factories?,但它处理用户定义函数的类型提示,在我的例子中,函数 item() 是一个预定义的库函数。

$doc = new DOMDocument();
$doc->loadXML('<x test="123"/>');
$list = $doc->getElementsByTagName('x');
if($list->length > 0)
    var_dump($list->item(0)->getAttribute('test'));

【问题讨论】:

只是为了做到这一点:您不能更改上面列出的任何代码?还是不能更改 item(0) 调用的实现? @nivekastoreth 只能更改空格 - 这包括添加作为空格子情况的 cmets。 已在 strubs 中修复。 github.com/JetBrains/phpstorm-stubs 外部库 -> PHP 运行时 -> 高级设置 -> 默认 srubs 路径:C:\User\Name\ 【参考方案1】:

根据official docs $list-&gt;item(0) 返回没有getAttribute() 方法的DOMNode 类的元素。 PhpStorm 在此处遵循官方文档。

但是如果你在你的代码中添加额外的行并在调试器中分析它(例如$z = $list-&gt;item(0);),你会看到$zDOMElement的实例,这样的方法。


A. 您不能即时将文档添加到预定义的方法(尤其是在链中)。没办法。

B. 正如你所看到的——这里的“问题”在文档中:他们说item() 返回一个类的实例,而在你的特定情况下它返回不同类的实例.


几个选项:

1. 修改您的代码以引入可以提供正确类型提示的中间变量。 据我了解,您不想使用它。

2. 忽略这些警告:您可以完全禁用它或仅针对该文件禁用它;您可以降低严重性(例如“信息”而不是“警告”)等

3. 更改文档(但不确定这是否是个好主意)。

这可以通过修改实际存根文件在全局级别完成(PhpStorm 发行版的一部分...所以它会影响所有项目,您必须在再次升级到新版本后重做)。

或者您可以在本地级别执行此操作(仅针对此项目):

从原始存根文件中提取 DOMNodeList 类的存根 将其放在项目中任何位置的单独文件中 更改item() 方法的@return 标记- 将其设置为@return DOMElement 任何你需要的东西。

这将使 IDE “合并”来自两个来源的文档:类似于 @return DOMNode|DOMElement

再一次——这将涵盖你的特殊情况——这将如何影响你的其他情况,我不知道。

【讨论】:

提取我没有想到的存根文件,这非常聪明——尽管我认为如果有人将其发送给我,我会拒绝该代码审查,因为如果 PHP 版本可能会导致误导性文档改变了。 嗯 .. 这仅适用于 IDE——这样的文件不需要包含在项目的实际代码库中(这也意味着:不要将此类文件放在实际项目中,只需链接它:通过附加内容根目录或包含路径)。【参考方案2】:

我不确定您无法编辑 PHP 语句但同时能够编辑 PHPDoc cmets 究竟是什么意思,但您可以通过执行以下操作来完成您的要求:

<?php
$doc = new DOMDocument();
$doc->loadXML('
<x test="123"/>');
$list = $doc->getElementsByTagName('x');
if($list->length > 0) 
    /** @var DomElement $element */
    $element = $list->item(0);
    var_dump($element->getAttribute('test'));

但这在技术上并不安全,因为 getElementsByTagName 返回一个 DomNodeList,它指定它包含 DomNodes(尽管我不够熟悉,不知道是否出于所有实际目的该列表将只包含 DomElements)

无论哪种方式,当我查看此示例代码时,所使用的方法已经正确记录,您的问题是您正在尝试指定,如上所述,在 DOM 代码中未(特别)强制执行的特殊约束/cmets。

【讨论】:

这正是我不想做的——将$list-&gt;item(0)-&gt;getAttribute('test') 分成几个部分并引入新变量。 想你可能会这么说。你只是说 list() 是预定义的,并不是说调用 $list->item() 的代码也是不可修改的。

以上是关于派生类返回值的 PhpStorm 类型提示的主要内容,如果未能解决你的问题,请参考以下文章

如何键入提示 Python 函数返回从超类派生的任何类的实例?

抽象类中的纯虚函数,返回类型为基/派生类型

在基类上自动推断派生类上函数的返回类型

C ++派生类覆盖返回类型

覆盖派生模板类的返回类型

如何允许派生类通过虚拟方法返回任何类型的迭代器?