如何从 PhpParser\Node\Stmt\Property 获取类名

问题描述 投票:0回答:1

我正在创建一个

Rector
(
rector/rector
) 规则,该规则应根据属性的某些属性来更改属性。
PhpParser
来自
nikic/php-parser

我获取属性没有问题,我只需检查当前

\PhpParser\Node
是否是
\PhpParser\Node\Stmt\Property
的实例(并且我确实得到了匹配项)。

但是,为了让我的用例匹配某些更改源数据,我还需要属性所属类的类名称 - 我尝试了以下简单的实现:

    private function getClassNameFromPropertyNode(Property $propertyNode): ?string {
        $currentNode = $propertyNode;
        while ($currentNode !== null) {
            if ($currentNode instanceof \PhpParser\Node\Stmt\Class_) {
                $name = $currentNode->name;
                return $name instanceof \PhpParser\Node\Identifier ? $name->toString() : null;
            }
            $currentNode =  $currentNode->getAttribute('parent');
        }
        return null;
    }

但它总是让我

null
...似乎
$currentNode->getAttribute('parent')
这总是返回null。

如何获取当前节点的父节点和/或当前属性的类名?谢谢。

nodes parent php-parser rector
1个回答
0
投票

我想我已经解决了。我回到https://github.com/nikic/PHP-Parser/issues/238,它给了我一个想法 - 父属性可能没有被校长设置,我是对的。

实际上有两个问题:

  1. 父节点未设置为
    parent
    属性
  2. getNodeTypes()
    校长的规矩连课都没上过

首先,我还需要遍历

Class_
节点:

use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Class_;
    ...
    public function getNodeTypes(): array
    {
        return [
            Property::class,
            Class_::class,
        ];
    }

然后在每个

refactor()
调用中将
parent
属性设置为当前类 FQN(完全限定名称 = 带命名空间的名称) - 为此,我首先简化了获取类名称的方法:

    private function getPropertyClassFqn(Property $propertyNode): ?string {
        $class = $propertyNode->getAttribute('parent');
        return ($class instanceof Class_) ? $class->namespacedName->toString() : null;
    }

然后在每个

refactor()
开始时我设置父级。
这是基于 Rector 始终在树中从上到下的假设。

use PhpParser\Node;
...
    public function refactor(Node $node): ?Node
    {
        if ($node instanceof Class_)
        {
            foreach ($node->stmts ?? [] as $childNode)
            {
                if ($childNode instanceof Property)
                {
                    $childNode->setAttribute('parent', $node);
                }
            }
            return $node;
        }
© www.soinside.com 2019 - 2024. All rights reserved.