Passed
Pull Request — master (#63)
by Aleksei
02:16
created

ArgumentException::renderClosureSignature()   B

Complexity

Conditions 9
Paths 20

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 9.0945

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 20
c 1
b 0
f 0
nc 20
nop 1
dl 0
loc 31
ccs 17
cts 19
cp 0.8947
crap 9.0945
rs 8.0555
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Injector;
6
7
use ReflectionNamedType;
8
use ReflectionUnionType;
9
10
abstract class ArgumentException extends \InvalidArgumentException
11
{
12
    protected const EXCEPTION_MESSAGE = 'Something is wrong with argument "%s" when calling "%s"%s.';
13
14 35
    public function __construct(\ReflectionFunctionAbstract $reflection, string $parameter)
15
    {
16 35
        $function = $reflection->getName();
17
        /** @psalm-var class-string|null $class */
18 35
        $class = $reflection->class ?? null;
19
20 35
        if ($class === null) {
21 29
            $method = $function;
22 29
            if (substr($method, -9) === '{closure}') {
23 29
                $method = $this->renderClosureSignature($reflection);
24
            }
25
        } else {
26 6
            $method = "{$class}::{$function}";
27
        }
28
29 35
        $fileName = $reflection->getFileName();
30 35
        $line = $reflection->getStartLine();
31
32 35
        $fileAndLine = '';
33 35
        if (!empty($fileName)) {
34 26
            $fileAndLine = " in \"$fileName\" at line $line";
35
        }
36
37 35
        parent::__construct(sprintf((string)static::EXCEPTION_MESSAGE, $parameter, $method, $fileAndLine));
38
    }
39
40 17
    private function renderClosureSignature(\ReflectionFunctionAbstract $reflection): string
41
    {
42 17
        $closureParameters = [];
43
44 17
        foreach ($reflection->getParameters() as $parameter) {
45 16
            $parameterString = \sprintf(
46
                '%s%s%s$%s',
47
                // type
48 16
                $this->renderParameterType($parameter),
49
                // reference
50 16
                $parameter->isPassedByReference() ? '&' : '',
51
                // variadic
52 16
                $parameter->isVariadic() ? '...' : '',
53 16
                $parameter->getName(),
54
            );
55 16
            if ($parameter->isDefaultValueAvailable()) {
56 3
                $default = $parameter->getDefaultValue();
57 3
                $parameterString .= ' = ';
58 3
                if (\is_object($default)) {
59
                    $parameterString .= 'new ' . \get_class($default) . '(...)';
60 3
                } elseif ($parameter->isDefaultValueConstant()) {
61
                    $parameterString .= $parameter->getDefaultValueConstantName();
62
                } else {
63 3
                    $parameterString .= \var_export($default, true);
64
                }
65
            }
66 16
            $closureParameters[] = \ltrim($parameterString);
67
        }
68
69 17
        $static = \method_exists($reflection, 'isStatic') && $reflection->isStatic() ? 'static ' : '';
70 17
        return $static . 'function (' . implode(', ', $closureParameters) . ')';
71
    }
72
73 16
    private function renderParameterType(\ReflectionParameter $parameter)
74
    {
75
        /** @var ReflectionNamedType|ReflectionUnionType|null $type */
76 16
        $type = $parameter->getType();
77 16
        if ($type instanceof ReflectionNamedType) {
78 13
            return sprintf(
79
                '%s%s ',
80 13
                $parameter->allowsNull() ? '?' : '',
81 13
                $type->getName()
82
            );
83
        }
84 7
        if ($type instanceof ReflectionUnionType) {
0 ignored issues
show
introduced by
$type is always a sub-type of ReflectionUnionType.
Loading history...
85
            /** @var ReflectionNamedType[] $types */
86 3
            $types = $type->getTypes();
87 3
            return \implode('|', \array_map(
88 3
                static fn (ReflectionNamedType $r) => $r->getName(),
89
                $types
90
            )) . ' ';
91
        }
92 4
        if ($type instanceof \ReflectionIntersectionType) {
0 ignored issues
show
Bug introduced by
The type ReflectionIntersectionType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
            /** @var ReflectionNamedType[] $types */
94
            $types = $type->getTypes();
95
            return \implode('&', \array_map(
96
                static fn (ReflectionNamedType $r) => $r->getName(),
97
                $types
98
            )) . ' ';
99
        }
100 4
        return '';
101
    }
102
}
103