Completed
Push — master ( 55cc51...e8a81f )
by
unknown
01:43
created

ExternalsVisitor::leaveNode()   F

Complexity

Conditions 27
Paths 2080

Size

Total Lines 97

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 27
nc 2080
nop 1
dl 0
loc 97
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Hal\Metric\Class_\Coupling;
3
4
use Hal\Metric\Helper\MetricClassNameGenerator;
5
use Hal\Metric\Metrics;
6
use PhpParser\Node;
7
use PhpParser\Node\Stmt;
8
use PhpParser\NodeVisitorAbstract;
9
10
/**
11
 * List externals dependencies
12
 *
13
 * @package Hal\Metric\Class_\Coupling
14
 */
15
class ExternalsVisitor extends NodeVisitorAbstract
16
{
17
18
    /**
19
     * @var Metrics
20
     */
21
    private $metrics;
22
23
    /**
24
     * @var Stmt\UseUse[]
25
     */
26
    private $uses = [];
27
28
    /**
29
     * @param Metrics $metrics
30
     */
31
    public function __construct(Metrics $metrics)
32
    {
33
        $this->metrics = $metrics;
34
    }
35
36
    /**
37
     * @inheritdoc
38
     */
39
    public function leaveNode(Node $node)
40
    {
41
42
        if ($node instanceof Stmt\Namespace_) {
43
            $this->uses = [];
44
        }
45
46
        if ($node instanceof Stmt\Use_) {
47
            $this->uses = array_merge($this->uses, $node->uses);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->uses, $node->uses) of type array is incompatible with the declared type array<integer,object<PhpParser\Node\Stmt\UseUse>> of property $uses.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
48
        }
49
50
        if ($node instanceof Stmt\Class_
51
            || $node instanceof Stmt\Interface_
52
            || $node instanceof Stmt\Trait_
53
        ) {
54
55
            $class = $this->metrics->get(MetricClassNameGenerator::getName($node));
56
            $parents = [];
57
58
            $dependencies = [];
59
60
            // extends
61
            if (isset($node->extends)) {
62
                if (is_array($node->extends)) {
63
                    foreach ((array)$node->extends as $interface) {
64
                        $this->pushToDependencies($dependencies, (string)$interface);
65
                        array_push($parents, (string)$interface);
66
                    }
67
                } else {
68
                    $this->pushToDependencies($dependencies, (string)$node->extends);
69
                    array_push($parents, (string)$node->extends);
70
                }
71
            }
72
73
            // implements
74
            if (isset($node->implements)) {
75
                foreach ($node->implements as $interface) {
76
                    $this->pushToDependencies($dependencies, (string)$interface);
77
                }
78
            }
79
80
            foreach ($node->stmts as $stmt) {
81
                if ($stmt instanceof Stmt\ClassMethod) {
82
                    // return
83
                    if (isset($stmt->returnType)) {
84
                        if ($stmt->returnType instanceof Node\Name\FullyQualified) {
85
                            $this->pushToDependencies($dependencies, (string)$stmt->returnType);
86
                        }
87
                    }
88
89
                    // Type hint of method's parameters
90
                    foreach ($stmt->params as $param) {
91
                        if ($param->type) {
92
                            if ($param->type instanceof Node\Name\FullyQualified) {
93
                                $this->pushToDependencies($dependencies, (string)$param->type);
94
                            }
95
                        }
96
                    }
97
98
                    // instantiations, static calls
99
                    \iterate_over_node($stmt, function ($node) use (&$dependencies) {
100
                        switch (true) {
101
                            case $node instanceof Node\Expr\New_:
102
                                // new MyClass
103
                                $this->pushToDependencies($dependencies, getNameOfNode($node));
104
                                break;
105
                            case $node instanceof Node\Expr\StaticCall:
106
                                // MyClass::Call
107
                                $this->pushToDependencies($dependencies, getNameOfNode($node));
108
                                break;
109
                        }
110
                    });
111
112
                    // annotations
113
                    $comments = $stmt->getDocComment();
114
                    if ($comments && false !== preg_match_all('!\s+\*\s+@(\w+)!', $comments->getText(), $matches)) {
115
                        foreach ($matches[1] as $check) {
116
                            foreach ($this->uses as $use) {
117
                                if (method_exists($use, 'getAlias')) {
118
                                    if (((string) $use->getAlias()) === $check) {
119
                                        $this->pushToDependencies($dependencies, (string)($use->name));
120
                                    }
121
                                    continue;
122
                                }
123
                                if ($use->alias === $check) {
124
                                    $this->pushToDependencies($dependencies, (string)($use->name));
125
                                }
126
                            }
127
                        }
128
                    }
129
                }
130
            }
131
132
            $class->set('externals', $dependencies);
133
            $class->set('parents', $parents);
134
        }
135
    }
136
137
    private function pushToDependencies(array &$dependencies, $dependency)
138
    {
139
        $lowercase = strtolower($dependency);
140
        if ('self' === $lowercase || 'parent' === $lowercase) {
141
            return;
142
        }
143
        array_push($dependencies, (string) $dependency);
144
    }
145
}
146
147