Completed
Push — master ( bfdea4...c674f5 )
by David
12s
created

AbstractMissingTypeHintRule::isNullable()   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
declare(strict_types=1);
3
4
namespace TheCodingMachine\PHPStan\Rules\TypeHints;
5
6
7
use phpDocumentor\Reflection\DocBlockFactory;
8
use phpDocumentor\Reflection\Type;
9
use phpDocumentor\Reflection\Types\Array_;
10
use phpDocumentor\Reflection\Types\Boolean;
11
use phpDocumentor\Reflection\Types\Callable_;
12
use phpDocumentor\Reflection\Types\Float_;
13
use phpDocumentor\Reflection\Types\Integer;
14
use phpDocumentor\Reflection\Types\Mixed_;
15
use phpDocumentor\Reflection\Types\Null_;
16
use phpDocumentor\Reflection\Types\Object_;
17
use phpDocumentor\Reflection\Types\Scalar;
18
use phpDocumentor\Reflection\Types\String_;
19
use PhpParser\Node;
20
use PHPStan\Analyser\Scope;
21
use PHPStan\Broker\Broker;
22
use PHPStan\Rules\Rule;
23
use Roave\BetterReflection\BetterReflection;
24
use Roave\BetterReflection\Reflection\ReflectionClass;
25
use Roave\BetterReflection\Reflection\ReflectionFunction;
26
use Roave\BetterReflection\Reflection\ReflectionMethod;
27
use Roave\BetterReflection\Reflection\ReflectionParameter;
28
use Roave\BetterReflection\TypesFinder\PhpDocumentor\NamespaceNodeToReflectionTypeContext;
29
use Roave\BetterReflection\TypesFinder\ResolveTypes;
30
31
abstract class AbstractMissingTypeHintRule implements Rule
32
{
33
34
    /**
35
     * @var Broker
36
     */
37
    private $broker;
38
39
    public function __construct(Broker $broker)
40
    {
41
        $this->broker = $broker;
42
    }
43
44
    abstract public function getNodeType(): string;
45
46
    /**
47
     * @param ReflectionMethod|ReflectionFunction $reflection
48
     * @return string
49
     */
50
    abstract public function getContext($reflection): string;
51
52
    abstract public function isReturnIgnored(Node $node): bool;
53
54
    /**
55
     * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod $node
56
     * @param \PHPStan\Analyser\Scope $scope
57
     * @return string[]
58
     */
59
    public function processNode(Node $node, Scope $scope): array
60
    {
61
        // TODO: improve performance by caching better reflection results.
62
        $finder = (new BetterReflection())->findReflectionsOnLine();
63
64
        if ($node->getLine() < 0) {
65
            // Fixes some problems with methods in anonymous class (the line number is poorly reported).
66
            return [];
67
        }
68
69
        $reflection = $finder($scope->getFile(), $node->getLine());
70
71
        // If the method implements/extends another method, we have no choice on the signature so let's bypass this check.
72
        if ($reflection instanceof ReflectionMethod && $this->isInherited($reflection)) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\Reflection\ReflectionMethod does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
73
            return [];
74
        }
75
76
        $errors = [];
77
78
        if ($reflection === null) {
79
            throw new \RuntimeException('Could not find item at '.$scope->getFile().':'.$node->getLine());
80
        }
81
82
        foreach ($reflection->getParameters() as $parameter) {
83
            $result = $this->analyzeParameter($parameter);
84
85
            if ($result !== null) {
86
                $errors[] = $result;
87
            }
88
        }
89
90
        if (!$this->isReturnIgnored($node)) {
91
            $returnTypeError = $this->analyzeReturnType($reflection);
92
            if ($returnTypeError !== null) {
93
                $errors[] = $returnTypeError;
94
            }
95
        }
96
97
        return $errors;
98
    }
99
100
    /**
101
     * Analyzes a parameter and returns the error string if xomething goes wrong or null if everything is ok.
102
     *
103
     * @param ReflectionParameter $parameter
104
     * @return null|string
105
     */
106
    private function analyzeParameter(ReflectionParameter $parameter): ?string
107
    {
108
        $typeResolver = new \phpDocumentor\Reflection\TypeResolver();
109
110
        $phpTypeHint = $parameter->getType();
111
        $docBlockTypeHints = $parameter->getDocBlockTypes();
112
113
        // If there is a type-hint, we have nothing to say unless it is an array.
114
        if ($phpTypeHint !== null) {
115
            $phpdocTypeHint = $typeResolver->resolve((string) $phpTypeHint);
116
117
            return $this->analyzeWithTypehint($parameter, $phpdocTypeHint, $docBlockTypeHints);
118
        } else {
119
            return $this->analyzeWithoutTypehint($parameter, $docBlockTypeHints);
120
        }
121
    }
122
123
    /**
124
     * @param ReflectionFunction|ReflectionMethod $function
125
     * @return null|string
126
     */
127
    private function analyzeReturnType($function): ?string
128
    {
129
        $reflectionPhpTypeHint = $function->getReturnType();
130
        $phpTypeHint = null;
131
        if ($reflectionPhpTypeHint !== null) {
132
            $typeResolver = new \phpDocumentor\Reflection\TypeResolver();
133
            $phpTypeHint = $typeResolver->resolve((string) $reflectionPhpTypeHint);
134
        }
135
        $docBlockTypeHints = $function->getDocBlockReturnTypes();
136
137
        // If there is a type-hint, we have nothing to say unless it is an array.
138
        if ($phpTypeHint !== null) {
139
            return $this->analyzeWithTypehint($function, $phpTypeHint, $docBlockTypeHints);
140
        } else {
141
            return $this->analyzeWithoutTypehint($function, $docBlockTypeHints);
142
        }
143
    }
144
145
    /**
146
     * @param ReflectionParameter|ReflectionMethod|ReflectionFunction $context
147
     * @param Type $phpTypeHint
148
     * @param Type[] $docBlockTypeHints
149
     * @return null|string
150
     */
151
    private function analyzeWithTypehint($context, Type $phpTypeHint, array $docBlockTypeHints): ?string
152
    {
153
        $docblockWithoutNullable = $this->typesWithoutNullable($docBlockTypeHints);
154
155
        if (!$phpTypeHint instanceof Array_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Array_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
156
            // Let's detect mismatches between docblock and PHP typehint
157
            foreach ($docblockWithoutNullable as $docblockTypehint) {
158
                if (get_class($docblockTypehint) !== get_class($phpTypeHint)) {
159
                    if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
160
                        return sprintf('%s, parameter $%s type is type-hinted to "%s" but the @param annotation says it is a "%s". Please fix the @param annotation.', $this->getContext($context), $context->getName(), (string) $phpTypeHint, (string) $docblockTypehint);
161
                    } else {
162
                        return sprintf('%s, return type is type-hinted to "%s" but the @return annotation says it is a "%s". Please fix the @return annotation.', $this->getContext($context), (string) $phpTypeHint, (string) $docblockTypehint);
163
                    }
164
                }
165
            }
166
167
            return null;
168
        }
169
170
        if (empty($docblockWithoutNullable)) {
171
            if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
172
                return sprintf('%s, parameter $%s type is "array". Please provide a @param annotation to further specify the type of the array. For instance: @param int[] $%s', $this->getContext($context), $context->getName(), $context->getName());
173
            } else {
174
                return sprintf('%s, return type is "array". Please provide a @param annotation to further specify the type of the array. For instance: @return int[]', $this->getContext($context));
175
            }
176
        } else {
177
            foreach ($docblockWithoutNullable as $docblockTypehint) {
178
                if (!$docblockTypehint instanceof Array_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Array_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
179
                    if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
180
                        return sprintf('%s, mismatching type-hints for parameter %s. PHP type hint is "array" and docblock type hint is %s.', $this->getContext($context), $context->getName(), (string)$docblockTypehint);
181
                    } else {
182
                        return sprintf('%s, mismatching type-hints for return type. PHP type hint is "array" and docblock declared return type is %s.', $this->getContext($context), (string)$docblockTypehint);
183
                    }
184
                }
185
186
                if ($docblockTypehint->getValueType() instanceof Mixed_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Mixed_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
187
                    if (!$this->findExplicitMixedArray($context)) {
188
                        if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
189
                            return sprintf('%s, parameter $%s type is "array". Please provide a more specific @param annotation in the docblock. For instance: @param int[] $%s. Use @param mixed[] $%s if this is really an array of mixed values.', $this->getContext($context), $context->getName(), $context->getName(), $context->getName());
190
                        } else {
191
                            return sprintf('%s, return type is "array". Please provide a more specific @return annotation. For instance: @return int[]. Use @return mixed[] if this is really an array of mixed values.', $this->getContext($context));
192
                        }
193
                    }
194
                }
195
            }
196
        }
197
198
        return null;
199
    }
200
201
    /**
202
     * @param ReflectionParameter|ReflectionMethod|ReflectionFunction $context
203
     * @return bool
204
     */
205
    private function findExplicitMixedArray($context) : bool
206
    {
207
        if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
208
            $context = $context->getDeclaringFunction();
209
        }
210
211
        $docComment = $context->getDocComment();
212
213
        // Very approximate solution: let's find in the whole docblock whether there is a mixed[] value or not.
214
        // TODO: improve this to target precisely the parameter or return type.
215
        return strpos($docComment, 'mixed[]') !== false;
216
    }
217
218
    /**
219
     * @param ReflectionParameter|ReflectionMethod|ReflectionFunction $context
220
     * @param Type[] $docBlockTypeHints
221
     * @return null|string
222
     */
223
    private function analyzeWithoutTypehint($context, array $docBlockTypeHints): ?string
224
    {
225
        if (empty($docBlockTypeHints)) {
226
            if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
227
                return sprintf('%s, parameter $%s has no type-hint and no @param annotation.', $this->getContext($context), $context->getName());
228
            } else {
229
                return sprintf('%s, there is no return type and no @return annotation.', $this->getContext($context));
230
            }
231
        }
232
233
        $nativeTypehint = $this->isNativelyTypehintable($docBlockTypeHints);
234
235
        if ($nativeTypehint !== null) {
236
            if ($context instanceof ReflectionParameter) {
0 ignored issues
show
Bug introduced by
The class Roave\BetterReflection\R...ion\ReflectionParameter does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
237
                return sprintf('%s, parameter $%s can be type-hinted to "%s".', $this->getContext($context), $context->getName(), $nativeTypehint);
238
            } else {
239
                return sprintf('%s, a "%s" return type can be added.', $this->getContext($context), $nativeTypehint);
240
            }
241
        }
242
243
        return null;
244
    }
245
246
    /**
247
     * @param Type[] $docBlockTypeHints
248
     * @return string|null
249
     */
250
    private function isNativelyTypehintable(array $docBlockTypeHints): ?string
251
    {
252
        if (count($docBlockTypeHints) > 2) {
253
            return null;
254
        }
255
        $isNullable = $this->isNullable($docBlockTypeHints);
256
        if (count($docBlockTypeHints) === 2 && !$isNullable) {
257
            return null;
258
        }
259
260
        $types = $this->typesWithoutNullable($docBlockTypeHints);
261
        // At this point, there is at most one element here
262
        if (empty($types)) {
263
            return null;
264
        }
265
266
        $type = $types[0];
267
268
        if ($this->isNativeType($type)) {
269
            return ($isNullable?'?':'').((string)$type);
270
        }
271
272
        if ($type instanceof Array_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Array_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
273
            return ($isNullable?'?':'').'array';
274
        }
275
276
        // TODO: more definitions to add here
277
        // Manage interface/classes
278
        // Manage array of things => (cast to array)
279
280
        if ($type instanceof Object_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Object_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
281
            return ($isNullable?'?':'').((string)$type);
282
        }
283
284
        return null;
285
    }
286
287
    private function isNativeType(Type $type): bool
288
    {
289
        if ($type instanceof String_
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\String_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
290
            || $type instanceof Integer
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Integer does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
291
            || $type instanceof Boolean
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Boolean does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
292
            || $type instanceof Float_
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Float_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
293
            || $type instanceof Scalar
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Scalar does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
294
            || $type instanceof Callable_
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Callable_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
295
            || ((string) $type) === 'iterable'
296
        ) {
297
            return true;
298
        }
299
        return false;
300
    }
301
302
    /**
303
     * @param Type[] $docBlockTypeHints
304
     * @return bool
305
     */
306
    private function isNullable(array $docBlockTypeHints): bool
307
    {
308
        foreach ($docBlockTypeHints as $docBlockTypeHint) {
309
            if ($docBlockTypeHint instanceof Null_) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Null_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
310
                return true;
311
            }
312
        }
313
        return false;
314
    }
315
316
    /**
317
     * Removes "null" from the list of types.
318
     *
319
     * @param Type[] $docBlockTypeHints
320
     * @return Type[]
321
     */
322
    private function typesWithoutNullable(array $docBlockTypeHints): array
323
    {
324
        return array_values(array_filter($docBlockTypeHints, function($item) {
325
            return !$item instanceof Null_;
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Reflection\Types\Null_ does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
326
        }));
327
    }
328
329
    private function isInherited(ReflectionMethod $method, ReflectionClass $class = null): bool
330
    {
331
        if ($class === null) {
332
            $class = $method->getDeclaringClass();
333
        }
334
        $interfaces = $class->getInterfaces();
335
        foreach ($interfaces as $interface) {
336
            if ($interface->hasMethod($method->getName())) {
337
                return true;
338
            }
339
        }
340
341
        $parentClass = $class->getParentClass();
342
        if ($parentClass !== null) {
343
            if ($parentClass->hasMethod($method->getName())) {
344
                return true;
345
            }
346
            return $this->isInherited($method, $parentClass);
347
        }
348
349
        return false;
350
    }
351
}
352