ElementNameResolver::beforeTraverse()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 3
cp 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @copyright 2010-2018 Mike van Riel<[email protected]>
11
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
12
 * @link      http://phpdoc.org
13
 */
14
15
namespace phpDocumentor\Reflection\NodeVisitor;
16
17
use phpDocumentor\Reflection\Fqsen;
18
use PhpParser\Node;
19
use PhpParser\Node\Const_;
20
use PhpParser\Node\Stmt\Class_;
21
use PhpParser\Node\Stmt\ClassConst;
22
use PhpParser\Node\Stmt\ClassMethod;
23
use PhpParser\Node\Stmt\Function_;
24
use PhpParser\Node\Stmt\Interface_;
25
use PhpParser\Node\Stmt\Namespace_;
26
use PhpParser\Node\Stmt\PropertyProperty;
27
use PhpParser\Node\Stmt\Trait_;
28
use PhpParser\NodeTraverser;
29
use PhpParser\NodeVisitorAbstract;
30
use SplDoublyLinkedList;
31
32
final class ElementNameResolver extends NodeVisitorAbstract
33
{
34
    /**
35
     * @var SplDoublyLinkedList
36
     */
37
    private $parts = null;
38
39
    /**
40
     * Resets the object to a known state before start processing.
41
     */
42
    public function beforeTraverse(array $nodes)
43
    {
44
        $this->resetState('\\');
45
    }
46
47
    /**
48
     * Performs a reset of the added element when needed.
49
     */
50 1
    public function leaveNode(Node $node)
51
    {
52 1
        switch (get_class($node)) {
53 1
            case Namespace_::class:
54 1
            case Class_::class:
55 1
            case ClassMethod::class:
56 1
            case Trait_::class:
57 1
            case PropertyProperty::class:
58 1
            case ClassConst::class:
59 1
            case Const_::class:
60 1
            case Interface_::class:
61 1
            case Function_::class:
62 1
                if (!$this->parts->isEmpty()) {
63 1
                    $this->parts->pop();
64
                }
65 1
                break;
66
        }
67 1
    }
68
69
    /**
70
     * Adds fqsen property to a node when applicable.
71
     *
72
     * @todo this method is decorating the Node with an $fqsen property...
73
     *       since we can't declare it in PhpParser/NodeAbstract,
74
     *       we should add a decorator class wrapper in Reflection...
75
     *       that should clear up the PHPSTAN errors about
76
     *       "access to an undefined property ::$fqsen".
77
     */
78 6
    public function enterNode(Node $node): ?int
79
    {
80 6
        switch (get_class($node)) {
81 6
            case Namespace_::class:
82 2
                $this->resetState('\\' . $node->name . '\\');
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
83 2
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
84 2
                break;
85 6
            case Class_::class:
86 4
            case Trait_::class:
87 4
            case Interface_::class:
88 4
                if (empty($node->name)) {
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
89 2
                    return NodeTraverser::DONT_TRAVERSE_CHILDREN;
90
                }
91
92 2
                $this->parts->push((string)$node->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
93 2
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
94 2
                break;
95 4
            case Function_::class:
96 1
                $this->parts->push($node->name . '()');
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
97 1
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
98 1
                return NodeTraverser::DONT_TRAVERSE_CHILDREN;
99 3
            case ClassMethod::class:
100
                $this->parts->push('::' . $node->name . '()');
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
101
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
102
                return NodeTraverser::DONT_TRAVERSE_CHILDREN;
103 3
            case ClassConst::class:
104 1
                $this->parts->push('::');
105 1
                break;
106 3
            case Const_::class:
107 2
                $this->parts->push($node->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
108 2
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
109 2
                break;
110 1
            case PropertyProperty::class:
111
                $this->parts->push('::$' . $node->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
112
                $node->fqsen = new Fqsen($this->buildName());
0 ignored issues
show
Bug introduced by
Accessing fqsen on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
113
                break;
114
        }
115
116 4
        return null;
117
    }
118
119
    /**
120
     * Resets the state of the object to an empty state.
121
     */
122 6
    private function resetState(?string $namespace = null): void
123
    {
124 6
        $this->parts = new SplDoublyLinkedList();
125 6
        $this->parts->push($namespace);
126 6
    }
127
128
    /**
129
     * Builds the name of the current node using the parts that are pushed to the parts list.
130
     */
131 5
    private function buildName(): string
132
    {
133 5
        $name = null;
134 5
        foreach ($this->parts as $part) {
135 5
            $name .= $part;
136
        }
137
138 5
        return rtrim((string) $name, '\\');
139
    }
140
}
141