Passed
Pull Request — master (#74)
by Sergei
12:58
created

ArgumentException   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Test Coverage

Coverage 89.29%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 97
ccs 50
cts 56
cp 0.8929
rs 10
wmc 18

3 Methods

Rating   Name   Duplication   Size   Complexity  
A renderParameterType() 0 28 5
A __construct() 0 25 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
    /**
25
     * @var string
26
     */
27
    protected const EXCEPTION_MESSAGE = 'Something is wrong with argument "%s" when calling "%s"%s.';
28
29 38
    public function __construct(ReflectionFunctionAbstract $reflection, string $parameter)
30
    {
31 38
        $function = $reflection->getName();
32
        /** @psalm-var class-string|null $class */
33 38
        $class = $reflection->class ?? null;
34
35 38
        if ($class === null) {
36 32
            $method = $function;
37 32
            if (substr($method, -9) === '{closure}') {
38 32
                $method = $this->renderClosureSignature($reflection);
39
            }
40
        } else {
41 6
            $method = "{$class}::{$function}";
42
        }
43
44 38
        $fileName = $reflection->getFileName();
45 38
        $line = $reflection->getStartLine();
46
47 38
        $fileAndLine = '';
48 38
        if (!empty($fileName)) {
49 29
            $fileAndLine = " in \"$fileName\" at line $line";
50
        }
51
52
        /** @psalm-suppress MixedArgument */
53 38
        parent::__construct(sprintf(static::EXCEPTION_MESSAGE, $parameter, $method, $fileAndLine));
54
    }
55
56 20
    private function renderClosureSignature(ReflectionFunctionAbstract $reflection): string
57
    {
58 20
        $closureParameters = [];
59
60 20
        foreach ($reflection->getParameters() as $parameter) {
61 19
            $parameterString = sprintf(
62 19
                '%s%s%s$%s',
63
                // type
64 19
                $this->renderParameterType($parameter),
65
                // reference
66 19
                $parameter->isPassedByReference() ? '&' : '',
67
                // variadic
68 19
                $parameter->isVariadic() ? '...' : '',
69 19
                $parameter->getName(),
70 19
            );
71 19
            if ($parameter->isDefaultValueAvailable()) {
72
                /** @var mixed $default */
73 6
                $default = $parameter->getDefaultValue();
74 6
                $parameterString .= ' = ';
75 6
                if (is_object($default)) {
76
                    $parameterString .= 'new ' . get_class($default) . '(...)';
77 6
                } elseif ($parameter->isDefaultValueConstant()) {
78
                    /** @psalm-suppress PossiblyNullOperand */
79 3
                    $parameterString .= $parameter->getDefaultValueConstantName();
80
                } else {
81 3
                    $parameterString .= var_export($default, true);
82
                }
83
            }
84 19
            $closureParameters[] = $parameterString;
85
        }
86
87 20
        $static = method_exists($reflection, 'isStatic') && $reflection->isStatic() ? 'static ' : '';
88 20
        return $static . 'function (' . implode(', ', $closureParameters) . ')';
89
    }
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 16
                '%s%s ',
98 16
                $parameter->allowsNull() ? '?' : '',
99 16
                $type->getName()
100 16
            );
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 3
                $types
108 3
            )) . ' ';
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