Completed
Branch master (7b4639)
by Johannes
13:16
created

DefinedSymbolCollector   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2
Metric Value
wmc 17
lcom 1
cbo 2
dl 0
loc 97
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A beforeTraverse() 0 6 1
A getDefinedSymbols() 0 4 1
A enterNode() 0 8 1
A recordClassDefinition() 0 6 2
A recordInterfaceDefinition() 0 6 2
A recordTraitDefinition() 0 6 2
A recordFunctionDefinition() 0 6 2
A recordConstDefinition() 0 8 3
A recordDefinitionOf() 0 13 2
1
<?php
2
3
namespace ComposerRequireChecker\NodeVisitor;
4
5
use PhpParser\Node;
6
use PhpParser\NodeVisitorAbstract;
7
8
final class DefinedSymbolCollector extends NodeVisitorAbstract
9
{
10
    /**
11
     * @var mixed[]
12
     */
13
    private $definedSymbols = [];
14
15
    public function __construct()
16
    {
17
    }
18
19
    /**
20
     * {@inheritDoc}
21
     */
22
    public function beforeTraverse(array $nodes)
23
    {
24
        $this->definedSymbols = [];
25
26
        return parent::beforeTraverse($nodes);
27
    }
28
29
    /**
30
     * @return string[]
31
     */
32
    public function getDefinedSymbols() : array
33
    {
34
        return array_keys($this->definedSymbols);
35
    }
36
37
    /**
38
     * {@inheritDoc}
39
     */
40
    public function enterNode(Node $node)
41
    {
42
        $this->recordClassDefinition($node);
43
        $this->recordInterfaceDefinition($node);
44
        $this->recordTraitDefinition($node);
45
        $this->recordFunctionDefinition($node);
46
        $this->recordConstDefinition($node);
47
    }
48
49
    private function recordClassDefinition(Node $node)
50
    {
51
        if ($node instanceof Node\Stmt\Class_) {
52
            $this->recordDefinitionOf($node);
53
        }
54
    }
55
56
    private function recordInterfaceDefinition(Node $node)
57
    {
58
        if ($node instanceof Node\Stmt\Interface_) {
59
            $this->recordDefinitionOf($node);
60
        }
61
    }
62
63
    private function recordTraitDefinition(Node $node)
64
    {
65
        if ($node instanceof Node\Stmt\Trait_) {
66
            $this->recordDefinitionOf($node);
67
        }
68
    }
69
70
    private function recordFunctionDefinition(Node $node)
71
    {
72
        if ($node instanceof Node\Stmt\Function_) {
73
            $this->recordDefinitionOf($node);
74
        }
75
    }
76
77
    private function recordConstDefinition(Node $node)
78
    {
79
        if ($node instanceof Node\Stmt\Const_) {
80
            foreach ($node->consts as $const) {
81
                $this->recordDefinitionOf($const);
82
            }
83
        }
84
    }
85
86
    /**
87
     * @param Node $node
88
     *
89
     * @return void
90
     */
91
    private function recordDefinitionOf(Node $node)
92
    {
93
        if (! isset($node->namespacedName)) {
0 ignored issues
show
Bug introduced by
Accessing namespacedName 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
            throw new \UnexpectedValueException(sprintf(
95
                'Given node of type "%s" (defined at line %s)does not have an assigned "namespacedName" property: '
96
                . 'did you pass it through a name resolver visitor?',
97
                get_class($node),
98
                $node->getLine()
99
            ));
100
        }
101
102
        $this->definedSymbols[(string) $node->namespacedName] = $node->namespacedName;
0 ignored issues
show
Bug introduced by
Accessing namespacedName 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...
103
    }
104
}
105