Passed
Push — master ( aa4419...7e0f99 )
by James
01:57
created

Comparator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Roave\ApiCompare;
5
6
use Roave\ApiCompare\Comparator\BackwardsCompatibility\ClassBased\ClassBased;
7
use Roave\BetterReflection\Reflection\ReflectionClass;
8
use Roave\BetterReflection\Reflection\ReflectionMethod;
9
use Roave\BetterReflection\Reflection\ReflectionParameter;
10
use Roave\BetterReflection\Reflector\ClassReflector;
11
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
12
13
final class Comparator
14
{
15
    /** @var ClassBased */
16
    private $classBasedComparisons;
17
18
    public function __construct(ClassBased $classBasedComparisons)
19
    {
20
        $this->classBasedComparisons = $classBasedComparisons;
21
    }
22
23
    public function compare(ClassReflector $oldApi, ClassReflector $newApi): Changes
24
    {
25
        $changelog = Changes::new();
26
27
        foreach ($oldApi->getAllClasses() as $oldClass) {
28
            $changelog = $this->examineClass($changelog, $oldClass, $newApi);
29
        }
30
31
        return $changelog;
32
    }
33
34
    private function examineClass(Changes $changelog, ReflectionClass $oldClass, ClassReflector $newApi): Changes
35
    {
36
        try {
37
            $newClass = $newApi->reflect($oldClass->getName());
38
39
            $changelog->mergeWith($this->classBasedComparisons->compare($oldClass, $newClass));
40
        } catch (IdentifierNotFound $exception) {
41
            $changelog = $changelog->withAddedChange(
42
                Change::removed(sprintf('Class %s has been deleted', $oldClass->getName()), true)
43
            );
44
            return $changelog;
45
        }
46
47
        if ($newClass->isFinal() && !$oldClass->isFinal()) {
0 ignored issues
show
Bug introduced by
The method isFinal() does not exist on Roave\BetterReflection\Reflection\Reflection. It seems like you code against a sub-type of Roave\BetterReflection\Reflection\Reflection such as Roave\BetterReflection\Reflection\ReflectionClass. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

47
        if ($newClass->/** @scrutinizer ignore-call */ isFinal() && !$oldClass->isFinal()) {
Loading history...
48
            $changelog = $changelog->withAddedChange(
49
                Change::changed(sprintf('Class %s is now final', $oldClass->getName()), true)
50
            );
51
        }
52
53
        foreach ($oldClass->getMethods() as $oldMethod) {
54
            $changelog = $this->examineMethod($changelog, $oldClass, $oldMethod, $newClass);
55
        }
56
57
        return $changelog;
58
    }
59
60
    private function examineMethod(
61
        Changes $changelog,
62
        ReflectionClass $oldClass,
63
        ReflectionMethod $oldMethod,
64
        ReflectionClass $newClass
65
    ): Changes {
66
        if ($oldMethod->isPrivate()) {
67
            return $changelog;
68
        }
69
70
        try {
71
            $newMethod = $newClass->getMethod($oldMethod->getName());
72
        } catch (\OutOfBoundsException $exception) {
73
            return $changelog->withAddedChange(
74
                Change::removed(
75
                    sprintf(
76
                        'Method %s in class %s has been deleted',
77
                        $oldMethod->getName(),
78
                        $oldClass->getName()
79
                    ),
80
                    true
81
                )
82
            );
83
        }
84
85
        foreach ($oldMethod->getParameters() as $parameterPosition => $oldParameter) {
86
            $changelog = $this->examineParameter(
87
                $changelog,
88
                $parameterPosition,
89
                $oldClass,
90
                $oldMethod,
91
                $oldParameter,
92
                $newMethod
93
            );
94
        }
95
96
        return $changelog;
97
    }
98
99
    private function examineParameter(
100
        Changes $changelog,
101
        int $parameterPosition,
102
        ReflectionClass $oldClass,
103
        ReflectionMethod $oldMethod,
104
        ReflectionParameter $oldParameter,
105
        ReflectionMethod $newMethod
106
    ): Changes {
107
        $newParameters = $newMethod->getParameters();
108
        if (!array_key_exists($parameterPosition, $newParameters)) {
109
            return $changelog->withAddedChange(
110
                Change::removed(
111
                    sprintf(
112
                        'Parameter %s (position %d) in %s%s%s has been deleted',
113
                        $oldParameter->getName(),
114
                        $parameterPosition,
115
                        $oldClass->getName(),
116
                        $oldMethod->isStatic() ? '#' : '::',
117
                        $oldMethod->getName()
118
                    ),
119
                    true
120
                )
121
            );
122
        }
123
124
        $newParameter = $newParameters[$parameterPosition];
0 ignored issues
show
Unused Code introduced by
The assignment to $newParameter is dead and can be removed.
Loading history...
125
126
        // @todo check if types changed, or becoming default
127
        // @todo check if a new param (without a default) was added
128
129
        return $changelog;
130
    }
131
}
132