Passed
Pull Request — master (#38)
by Marco
03:11
created

functionOrMethodName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 3
eloc 5
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\ApiCompare\Comparator\BackwardsCompatibility\FunctionBased;
6
7
use Roave\ApiCompare\Change;
8
use Roave\ApiCompare\Changes;
9
use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract;
10
use Roave\BetterReflection\Reflection\ReflectionMethod;
11
use Roave\BetterReflection\Reflection\ReflectionParameter;
12
13
/**
14
 * A parameter passed by-value and a parameter passed by-reference are wildly different, so changing
15
 * the by-ref flag can lead to unexpected state mutations or lack thereof, and should therefore be
16
 * considered a BC break.
17
 */
18
final class ParameterByReferenceChanged implements FunctionBased
19
{
20
    public function compare(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
21
    {
22
        /** @var ReflectionParameter[] $fromParameters */
23
        $fromParameters = array_values($fromFunction->getParameters());
24
        /** @var ReflectionParameter[] $toParameters */
25
        $toParameters = array_values($toFunction->getParameters());
26
27
        $changes = Changes::new();
28
29
        foreach (array_intersect_key($fromParameters, $toParameters) as $parameterIndex => $commonParameter) {
30
            $changes = $changes->mergeWith($this->compareParameter($commonParameter, $toParameters[$parameterIndex]));
31
        }
32
33
        return $changes;
34
    }
35
36
    private function compareParameter(ReflectionParameter $fromParameter, ReflectionParameter $toParameter) : Changes
37
    {
38
        $fromByReference = $fromParameter->isPassedByReference();
39
        $toByReference   = $toParameter->isPassedByReference();
40
41
        if ($fromByReference === $toByReference) {
42
            return Changes::new();
43
        }
44
45
        return Changes::fromArray([
46
            Change::changed(
47
                sprintf(
48
                    'The parameter $%s of %s() changed from %s to %s',
49
                    $fromParameter->getName(),
50
                    $this->functionOrMethodName($fromParameter->getDeclaringFunction()),
51
                    $this->referenceToString($fromByReference),
52
                    $this->referenceToString($toByReference)
53
                ),
54
                true
55
            ),
56
        ]);
57
    }
58
59
    private function functionOrMethodName(ReflectionFunctionAbstract $function) : string
60
    {
61
        if ($function instanceof ReflectionMethod) {
62
            return $function->getDeclaringClass()->getName()
63
                . ($function->isStatic() ? '::' : '#')
64
                . $function->getName();
65
        }
66
67
        return $function->getName();
68
    }
69
70
    private function referenceToString(bool $reference) : string
71
    {
72
        return $reference ? 'by-reference' : 'by-value';
73
    }
74
}
75