Passed
Push — master ( eea8cf...527f74 )
by Alexander
03:17 queued 01:07
created

ArgumentException   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Test Coverage

Coverage 91.67%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
dl 0
loc 97
ccs 44
cts 48
cp 0.9167
rs 10
c 1
b 0
f 0
wmc 18

3 Methods

Rating   Name   Duplication   Size   Complexity  
A renderParameterType() 0 28 5
A __construct() 0 24 4
B renderClosureSignature() 0 33 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Injector;
6
7
use ReflectionFunctionAbstract;
8
use 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...
9
use ReflectionNamedType;
10
use ReflectionParameter;
11
use ReflectionUnionType;
12
13
use function array_map;
14
use function get_class;
15
use function implode;
16
use function is_object;
17
use function method_exists;
18
use function sprintf;
19
use function substr;
20
use function var_export;
21
22
abstract class ArgumentException extends \InvalidArgumentException
23
{
24
    protected const EXCEPTION_MESSAGE = 'Something is wrong with argument "%s" when calling "%s"%s.';
25
26 38
    public function __construct(ReflectionFunctionAbstract $reflection, string $parameter)
27
    {
28 38
        $function = $reflection->getName();
29
        /** @psalm-var class-string|null $class */
30 38
        $class = $reflection->class ?? null;
31
32 38
        if ($class === null) {
33 32
            $method = $function;
34 32
            if (substr($method, -9) === '{closure}') {
35 32
                $method = $this->renderClosureSignature($reflection);
36
            }
37
        } else {
38 6
            $method = "{$class}::{$function}";
39
        }
40
41 38
        $fileName = $reflection->getFileName();
42 38
        $line = $reflection->getStartLine();
43
44 38
        $fileAndLine = '';
45 38
        if (!empty($fileName)) {
46 29
            $fileAndLine = " in \"$fileName\" at line $line";
47
        }
48
49 38
        parent::__construct(sprintf((string)static::EXCEPTION_MESSAGE, $parameter, $method, $fileAndLine));
50
    }
51
52 20
    private function renderClosureSignature(ReflectionFunctionAbstract $reflection): string
53
    {
54 20
        $closureParameters = [];
55
56 20
        foreach ($reflection->getParameters() as $parameter) {
57 19
            $parameterString = sprintf(
58
                '%s%s%s$%s',
59
                // type
60 19
                $this->renderParameterType($parameter),
61
                // reference
62 19
                $parameter->isPassedByReference() ? '&' : '',
63
                // variadic
64 19
                $parameter->isVariadic() ? '...' : '',
65 19
                $parameter->getName(),
66
            );
67 19
            if ($parameter->isDefaultValueAvailable()) {
68
                /** @var mixed $default */
69 6
                $default = $parameter->getDefaultValue();
70 6
                $parameterString .= ' = ';
71 6
                if (is_object($default)) {
72
                    $parameterString .= 'new ' . get_class($default) . '(...)';
73 6
                } elseif ($parameter->isDefaultValueConstant()) {
74
                    /** @psalm-suppress PossiblyNullOperand */
75 3
                    $parameterString .= $parameter->getDefaultValueConstantName();
76
                } else {
77 3
                    $parameterString .= var_export($default, true);
78
                }
79
            }
80 19
            $closureParameters[] = $parameterString;
81
        }
82
83 20
        $static = method_exists($reflection, 'isStatic') && $reflection->isStatic() ? 'static ' : '';
84 20
        return $static . 'function (' . implode(', ', $closureParameters) . ')';
85
    }
86
87
    /**
88
     * @psalm-suppress UndefinedDocblockClass
89
     * @psalm-suppress UndefinedClass
90
     */
91 19
    private function renderParameterType(ReflectionParameter $parameter): string
92
    {
93
        /** @var ReflectionIntersectionType|ReflectionNamedType|ReflectionUnionType|null $type */
94 19
        $type = $parameter->getType();
95 19
        if ($type instanceof ReflectionNamedType) {
96 16
            return sprintf(
97
                '%s%s ',
98 16
                $parameter->allowsNull() ? '?' : '',
99 16
                $type->getName()
100
            );
101
        }
102 7
        if ($type instanceof ReflectionUnionType) {
0 ignored issues
show
introduced by
$type is always a sub-type of ReflectionUnionType.
Loading history...
103
            /** @var ReflectionNamedType[] $types */
104 3
            $types = $type->getTypes();
105 3
            return implode('|', array_map(
106 3
                static fn (ReflectionNamedType $r) => $r->getName(),
107
                $types
108
            )) . ' ';
109
        }
110 4
        if ($type instanceof ReflectionIntersectionType) {
111
            /** @var ReflectionNamedType[] $types */
112
            $types = $type->getTypes();
113
            return implode('&', array_map(
114
                static fn (ReflectionNamedType $r) => $r->getName(),
115
                $types
116
            )) . ' ';
117
        }
118 4
        return '';
119
    }
120
}
121