Passed
Pull Request — master (#108)
by Marco
02:35
created

ParameterTypeChanged::typeToString()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased;
6
7
use Roave\BackwardCompatibility\Change;
8
use Roave\BackwardCompatibility\Changes;
9
use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName;
10
use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract;
11
use Roave\BetterReflection\Reflection\ReflectionParameter;
12
use Roave\BetterReflection\Reflection\ReflectionType;
13
use function array_intersect_key;
14
use function array_values;
15
use function sprintf;
16
17
/**
18
 * Detects a change in a parameter type
19
 *
20
 * This is mostly useful for methods, where a change in a parameter type is not allowed in
21
 * inheritance/interface scenarios.
22
 */
23
final class ParameterTypeChanged implements FunctionBased
24
{
25
    /** @var ReflectionFunctionAbstractName */
26
    private $formatFunction;
27
28
    public function __construct()
29
    {
30
        $this->formatFunction = new ReflectionFunctionAbstractName();
31
    }
32
33
    public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
34
    {
35
        return Changes::fromIterator($this->checkSymbols(
36
            array_values($fromFunction->getParameters()),
37
            array_values($toFunction->getParameters())
38
        ));
39
    }
40
41
    /**
42
     * @param ReflectionParameter[] $from
43
     * @param ReflectionParameter[] $to
44
     *
45
     * @return iterable|Change[]
46
     */
47
    private function checkSymbols(array $from, array $to) : iterable
48
    {
49
        foreach (array_intersect_key($from, $to) as $index => $commonParameter) {
50
            yield from $this->compareParameter($commonParameter, $to[$index]);
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type iterable|Roave\BackwardCompatibility\Change[].
Loading history...
51
        }
52
    }
53
54
    /**
55
     * @return iterable|Change[]
56
     */
57
    private function compareParameter(ReflectionParameter $fromParameter, ReflectionParameter $toParameter) : iterable
58
    {
59
        $fromType = $this->typeToString($fromParameter->getType());
60
        $toType   = $this->typeToString($toParameter->getType());
61
62
        if ($fromType !== $toType) {
63
            yield Change::changed(
0 ignored issues
show
Bug Best Practice introduced by
The expression yield Roave\BackwardComp...omType, $toType), true) returns the type Generator which is incompatible with the documented return type iterable|Roave\BackwardCompatibility\Change[].
Loading history...
64
                sprintf(
65
                    'The parameter $%s of %s changed from %s to %s',
66
                    $fromParameter->getName(),
67
                    $this->formatFunction->__invoke($fromParameter->getDeclaringFunction()),
68
                    $fromType,
69
                    $toType
70
                ),
71
                true
72
            );
73
        }
74
    }
75
76
    private function typeToString(?ReflectionType $type) : string
77
    {
78
        if (! $type) {
79
            return 'no type';
80
        }
81
82
        return ($type->allowsNull() ? '?' : '')
83
            . $type->__toString();
84
    }
85
}
86