Completed
Push — master ( bdaaad...4f4372 )
by personal
06:57 queued 04:36
created

ExternalsVisitor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Hal\Metric\Class_\Coupling;
3
4
use Hal\Metric\Metrics;
5
use PhpParser\Node;
6
use PhpParser\Node\Stmt;
7
use PhpParser\NodeVisitorAbstract;
8
9
/**
10
 * List externals dependencies
11
 *
12
 * Class ExternalsVisitor
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\Use_[]
25
     */
26
    private $uses = [];
27
28
    /**
29
     * ClassEnumVisitor constructor.
30
     * @param Metrics $metrics
31
     */
32
    public function __construct(Metrics $metrics)
33
    {
34
        $this->metrics = $metrics;
35
    }
36
37
    /**
38
     * @inheritdoc
39
     */
40
    public function leaveNode(Node $node)
41
    {
42
43
        if ($node instanceof Stmt\Namespace_) {
44
            $this->uses = [];
45
        }
46
47
        if ($node instanceof Stmt\Use_) {
48
            $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\Use_>> 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...
49
        }
50
51
        if ($node instanceof Stmt\Class_
52
            || $node instanceof Stmt\Interface_
53
        ) {
54
55
            $class = $this->metrics->get($node->namespacedName->toString());
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $class is correct as $this->metrics->get($nod...spacedName->toString()) (which targets Hal\Metric\Metrics::get()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
56
            $nodeClass = $node;
0 ignored issues
show
Unused Code introduced by
$nodeClass is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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
                        array_push($dependencies, (string)$interface);
65
                    }
66
                } else {
67
                    array_push($dependencies, (string)$node->extends);
68
                }
69
            }
70
71
            // implements
72
            if (isset($node->implements)) {
73
                foreach ($node->implements as $interface) {
74
                    array_push($dependencies, (string)$interface);
75
                }
76
            }
77
78
            foreach ($node->stmts as $stmt) {
79
                if ($stmt instanceof Stmt\ClassMethod) {
80
81
82
                    // return
83
                    if (isset($stmt->returnType)) {
84
                        if ($stmt->returnType instanceof Node\Name\FullyQualified) {
85
                            array_push($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
                                array_push($dependencies, (string)$param->type);
94
                            }
95
                        }
96
                    }
97
98
                    // instanciations, static calls
99
                    \iterate_over_node($stmt, function ($node) use (&$dependencies) {
100 View Code Duplication
                        switch (true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
                            case $node instanceof Node\Expr\New_:
102
                                // new MyClass
103
                                array_push($dependencies, getNameOfNode($node));
104
                                break;
105
                            case $node instanceof Node\Expr\StaticCall:
106
                                // MyClass::Call
107
                                array_push($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 ($use->alias === $check) {
118
                                    array_push($dependencies, (string)($use->name));
119
                                }
120
                            }
121
                        }
122
                    }
123
                }
124
            }
125
126
            $class->set('externals', $dependencies);
0 ignored issues
show
Bug introduced by
The method set cannot be called on $class (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
127
        }
128
    }
129
}
130
131