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

UsedSymbolCollector::recordClassExpressionUsage()   B

Complexity

Conditions 8
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 16
rs 7.7778
c 1
b 0
f 0
cc 8
eloc 10
nc 2
nop 1
1
<?php
2
3
namespace ComposerRequireChecker\NodeVisitor;
4
5
use PhpParser\Node;
6
use PhpParser\NodeVisitorAbstract;
7
8
final class UsedSymbolCollector extends NodeVisitorAbstract
9
{
10
    /**
11
     * @var mixed[]
12
     */
13
    private $collectedSymbols = [];
14
15
    public function __construct()
16
    {
17
    }
18
19
    /**
20
     * @return string[]
21
     */
22
    public function getCollectedSymbols() : array
23
    {
24
        return array_keys($this->collectedSymbols);
25
    }
26
27
    /**
28
     * {@inheritDoc}
29
     */
30
    public function beforeTraverse(array $nodes)
31
    {
32
        $this->collectedSymbols = [];
33
34
        return parent::beforeTraverse($nodes);
35
    }
36
37
    /**
38
     * {@inheritDoc}
39
     */
40
    public function enterNode(Node $node)
41
    {
42
        $this->recordExtendsUsage($node);
43
        $this->recordImplementsUsage($node);
44
        $this->recordClassExpressionUsage($node);
45
        $this->recordCatchUsage($node);
46
        $this->recordFunctionCallUsage($node);
47
        $this->recordFunctionParameterTypesUsage($node);
48
        $this->recordFunctionReturnTypeUsage($node);
49
        $this->recordConstantFetchUsage($node);
50
        $this->recordTraitUsage($node);
51
52
        return parent::enterNode($node);
53
    }
54
55
    private function recordExtendsUsage(Node $node)
56
    {
57
        if ($node instanceof Node\Stmt\Class_) {
58
            array_map([$this, 'recordUsageOf'], array_filter([$node->extends]));
59
        }
60
61
        if ($node instanceof Node\Stmt\Interface_) {
62
            array_map([$this, 'recordUsageOf'], array_filter($node->extends));
63
        }
64
    }
65
66
    private function recordImplementsUsage(Node $node)
67
    {
68
        if ($node instanceof Node\Stmt\Class_) {
69
            array_map([$this, 'recordUsageOf'], $node->implements);
70
        }
71
    }
72
73
    private function recordClassExpressionUsage(Node $node)
74
    {
75
        if (
76
            (
77
                $node instanceof Node\Expr\StaticCall
78
                || $node instanceof Node\Expr\StaticPropertyFetch
79
                || $node instanceof Node\Expr\ClassConstFetch
80
                || $node instanceof Node\Expr\New_
81
                || $node instanceof Node\Expr\Instanceof_
82
            )
83
            && ($nodeClass = $node->class)
84
            && $nodeClass instanceof Node\Name
85
        ) {
86
            $this->recordUsageOf($nodeClass);
87
        }
88
    }
89
90
    private function recordCatchUsage(Node $node)
91
    {
92
        if ($node instanceof Node\Stmt\Catch_) {
93
            $this->recordUsageOf($node->type);
94
        }
95
    }
96
97
    private function recordFunctionCallUsage(Node $node)
98
    {
99
        if (
100
            $node instanceof Node\Expr\FuncCall
101
            && ($nodeName = $node->name)
102
            && $nodeName instanceof Node\Name
103
        ) {
104
            $this->recordUsageOf($nodeName);
105
        }
106
    }
107
108
    private function recordFunctionParameterTypesUsage(Node $node)
109
    {
110
        if ($node instanceof Node\Stmt\Function_
111
            || $node instanceof Node\Stmt\ClassMethod
112
        ) {
113
            foreach ($node->getParams() as $param) {
114
                if ($param->type instanceof Node\Name) {
115
                    $this->recordUsageOf($param->type);
116
                }
117
                if (is_string($param->type)) {
118
                    $this->recordUsageOfByString($param->type);
119
                }
120
            }
121
        }
122
    }
123
124
    private function recordFunctionReturnTypeUsage(Node $node)
125
    {
126
        if ($node instanceof Node\Stmt\Function_
127
            || $node instanceof Node\Stmt\ClassMethod
128
        ) {
129
            if ($node->getReturnType() instanceof Node\Name) {
130
                $this->recordUsageOf($node->getReturnType());
131
            }
132
            if (is_string($node->getReturnType())) {
133
                $this->recordUsageOfByString($node->getReturnType());
134
            }
135
        }
136
    }
137
138
    private function recordConstantFetchUsage(Node $node)
139
    {
140
        if ($node instanceof Node\Expr\ConstFetch) {
141
            $this->recordUsageOf($node->name);
142
        }
143
    }
144
145
    private function recordTraitUsage(Node $node)
146
    {
147
        if (! $node instanceof Node\Stmt\TraitUse) {
148
            return;
149
        }
150
151
        array_map([$this, 'recordUsageOf'], $node->traits);
152
153
        foreach ($node->adaptations as $adaptation) {
154
            $this->recordUsageOf($adaptation->trait);
155
156
            if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) {
157
                array_map([$this, 'recordUsageOf'], $adaptation->insteadof);
158
            }
159
        }
160
    }
161
162
    /**
163
     * @param Node\Name $symbol
164
     *
165
     * @return void
166
     */
167
    private function recordUsageOf(Node\Name $symbol)
168
    {
169
        $this->collectedSymbols[(string) $symbol] = $symbol;
170
    }
171
172
    /**
173
     * @param Node\Name $symbol
174
     *
175
     * @return void
176
     */
177
    private function recordUsageOfByString(string $symbol)
178
    {
179
        $this->collectedSymbols[$symbol] = $symbol;
180
    }
181
}
182