Passed
Pull Request — drop-php74 (#272)
by Akihito
03:33 queued 01:20
created

OptionsMethodRequest::ignoreAnnotatedPrameter()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 19
rs 9.9332
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use Doctrine\Common\Annotations\Reader;
8
use ReflectionException;
9
use ReflectionMethod;
10
use ReflectionNamedType;
11
use ReflectionParameter;
12
13
use function assert;
14
use function is_array;
15
use function is_string;
16
use function method_exists;
17
18
final class OptionsMethodRequest
19
{
20
    public function __construct(
21
        private Reader $reader,
22
    ) {
23
    }
24
25
    /**
26
     * Parameter #2 $paramMetas of method BEAR\Resource\OptionsMethodRequest::ignoreAnnotatedPrameter() expects array('parameters' => array<string, array('type' =>
27
     *
28
     * @param array<string, array{type: string, description?: string}> $paramDoc
29
     * @param array<string, string>                                    $ins
30
     *
31
     * @return array{parameters?: array<string, array{type?: string, description?: string, default?: string}>, required?: array<int, string>}
32
     */
33
    public function __invoke(ReflectionMethod $method, array $paramDoc, array $ins): array
34
    {
35
        return $this->getParamMetas($method->getParameters(), $paramDoc, $ins);
36
37
        return $this->ignoreAnnotatedPrameter($method, $paramMetas);
0 ignored issues
show
Unused Code introduced by
return $this->ignoreAnno...r($method, $paramMetas) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
38
    }
39
40
    /**
41
     * @param array<string, array{type?: string, description?: string}> $paramDoc
42
     *
43
     * @psalm-suppress RedundantCondition for BC
44
     */
45
    private function getParameterType(ReflectionParameter $parameter, array $paramDoc, string $name): string|null
46
    {
47
        $hasType = method_exists($parameter, 'getType') && $parameter->getType();
48
        if ($hasType) {
49
            return $this->getType($parameter);
50
        }
51
52
        if (isset($paramDoc[$name]['type'])) {
53
            return $paramDoc[$name]['type'];
54
        }
55
56
        return null;
57
    }
58
59
    /**
60
     * @param array<ReflectionParameter>                               $parameters
61
     * @param array<string, array{type: string, description?: string}> $paramDoc
62
     * @param array<string, string>                                    $ins
63
     *
64
     * @return array{parameters?: array<string, array{type?: string}>, required?: array<int, string>}
65
     */
66
    private function getParamMetas(array $parameters, array $paramDoc, array $ins): array
67
    {
68
        foreach ($parameters as $parameter) {
69
            $name = (string) $parameter->name;
70
            if (isset($ins[$name])) {
71
                $paramDoc[$name]['in'] = $ins[$parameter->name];
72
            }
73
74
            if (! isset($paramDoc[$parameter->name])) {
75
                $paramDoc[$name] = [];
76
            }
77
78
            $paramDoc = $this->paramType($paramDoc, $parameter);
79
            $paramDoc = $this->paramDefault($paramDoc, $parameter);
80
        }
81
82
        $required = $this->getRequired($parameters);
83
84
        return $this->setParamMetas($paramDoc, $required);
85
    }
86
87
    /**
88
     * @param array<ReflectionParameter> $parameters
89
     *
90
     * @return string[]
91
     * @psalm-return list<string>
92
     */
93
    private function getRequired(array $parameters): array
94
    {
95
        $required = [];
96
        foreach ($parameters as $parameter) {
97
            if ($parameter->isOptional()) {
98
                continue;
99
            }
100
101
            $required[] = $parameter->name;
102
        }
103
104
        return $required;
105
    }
106
107
    /**
108
     * @param array<string, array{type?: string, description?: string}> $paramDoc
109
     *
110
     * @return array<string, array{type?: string, description?: string, default?: string}>
111
     *
112
     * @throws ReflectionException
113
     */
114
    private function paramDefault(array $paramDoc, ReflectionParameter $parameter): array
115
    {
116
        $hasDefault = $parameter->isDefaultValueAvailable() && $parameter->getDefaultValue() !== null;
117
        if ($hasDefault) {
118
            $default = $parameter->getDefaultValue();
119
            $paramDoc[(string) $parameter->name]['default'] = is_array($default) ? '[]' : (string) $parameter->getDefaultValue(); // @phpstan-ignore-lines
120
        }
121
122
        return $paramDoc;
123
    }
124
125
    /**
126
     * @param array<string, array{type?: string, description?: string, default?: string, in?: string}> $paramDoc
127
     *
128
     * @return array<string, array{type?: string, description?: string, default?: string, in?: string}>
129
     */
130
    private function paramType(array $paramDoc, ReflectionParameter $parameter): array
131
    {
132
        $type = $this->getParameterType($parameter, $paramDoc, $parameter->name);
133
        if (is_string($type)) {
134
            $paramDoc[(string) $parameter->name]['type'] = $type; // override type parameter by reflection over phpdoc param type
135
        }
136
137
        return $paramDoc;
138
    }
139
140
    private function getType(ReflectionParameter $parameter): string
141
    {
142
        $namedType = $parameter->getType();
143
        assert($namedType instanceof ReflectionNamedType);
144
        $type = $namedType->getName();
145
        if ($type === 'int') {
146
            $type = 'integer';
147
        }
148
149
        return $type;
150
    }
151
152
    /**
153
     * @param array<string, array{type?: string}> $paramDoc
154
     * @param list<string>                        $required
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\list 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...
155
     *
156
     * @return array{parameters?: array<string, array{type?: string}>, required?: array<int, string>}
157
     */
158
    private function setParamMetas(array $paramDoc, array $required): array
159
    {
160
        $paramMetas = [];
161
        if ((bool) $paramDoc) {
162
            $paramMetas['parameters'] = $paramDoc;
163
        }
164
165
        if ((bool) $required) {
166
            $paramMetas['required'] = $required;
167
        }
168
169
        return $paramMetas;
170
    }
171
}
172