Skip to content

Commit cb60937

Browse files
chore: introduce phpstan level 6 (#7269)
1 parent 82ab5ef commit cb60937

25 files changed

+164
-68
lines changed

.php-cs-fixer.dist.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
->setRules([
3434
'@DoctrineAnnotation' => true,
3535
'@PHP71Migration' => true,
36-
'@PHP71Migration:risky' => true,
36+
'@PHP70Migration:risky' => true,
3737
'@PHPUnit60Migration:risky' => true,
3838
'@Symfony' => true,
3939
'@Symfony:risky' => true,
@@ -76,7 +76,7 @@
7676
],
7777
'no_superfluous_elseif' => true,
7878
'no_superfluous_phpdoc_tags' => [
79-
'allow_mixed' => false,
79+
'allow_mixed' => true, // For PHPStan
8080
'allow_unused_params' => true,
8181
],
8282
'no_unset_cast' => true,
@@ -98,9 +98,6 @@
9898
'php_unit_test_annotation' => [
9999
'style' => 'prefix',
100100
],
101-
'phpdoc_add_missing_param_annotation' => [
102-
'only_untyped' => true,
103-
],
104101
'phpdoc_no_alias_tag' => true,
105102
'phpdoc_order' => true,
106103
'phpdoc_trim_consecutive_blank_line_separation' => true,

phpstan.neon.dist

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 5
2+
level: 6
33
paths:
44
- src
55
- tests
@@ -112,3 +112,63 @@ parameters:
112112

113113
# Allow extra assertions in tests: https://github.com/phpstan/phpstan-strict-rules/issues/130
114114
- '#^Call to (static )?method PHPUnit\\Framework\\Assert::.* will always evaluate to true\.$#'
115+
116+
# Level 6
117+
-
118+
identifier: missingType.iterableValue
119+
-
120+
identifier: missingType.generics
121+
-
122+
identifier: missingType.property
123+
paths:
124+
- src/Doctrine/Common/Tests
125+
- src/Doctrine/Odm/Tests
126+
- src/Doctrine/Orm/Tests
127+
- src/Elasticsearch/Tests
128+
- src/Hydra/Tests
129+
- src/JsonApi/Tests
130+
- src/JsonSchema/Tests
131+
- src/Metadata/Tests
132+
- src/Serializer/Tests
133+
- src/Symfony/Tests
134+
- tests
135+
-
136+
identifier: missingType.parameter
137+
paths:
138+
- src/Doctrine/Common/Tests
139+
- src/Doctrine/Odm/Tests
140+
- src/Doctrine/Orm/Tests
141+
- src/Elasticsearch/Tests
142+
- src/GraphQl/Tests
143+
- src/Hydra/Tests
144+
- src/JsonApi/Tests
145+
- src/JsonSchema/Tests
146+
- src/Metadata/Tests
147+
- src/OpenApi/Tests
148+
- src/Serializer/Tests
149+
- src/Symfony/Bundle/Test
150+
- src/Symfony/Tests
151+
- tests
152+
- src # TODO
153+
-
154+
identifier: missingType.return
155+
paths:
156+
- src/Doctrine/Common/Tests
157+
- src/Doctrine/Odm/Tests
158+
- src/Doctrine/Orm/Tests
159+
- src/Elasticsearch/Tests
160+
- src/GraphQl/Tests
161+
- src/Hydra/Tests
162+
- src/JsonApi/Tests
163+
- src/JsonSchema/Tests
164+
- src/Metadata/Tests
165+
- src/OpenApi/Tests
166+
- src/Serializer/Tests
167+
- src/Symfony/Tests
168+
- tests
169+
-
170+
identifier: argument.templateType
171+
paths:
172+
- src/Symfony/Bundle/Test
173+
- tests
174+
- src # TODO

src/GraphQl/Resolver/Factory/ResolverFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function __invoke(?string $resourceClass = null, ?string $rootClass = nul
8787
};
8888
}
8989

90-
private function resolve(?array $source, array $args, ResolveInfo $info, ?string $rootClass = null, ?Operation $operation = null, mixed $body = null)
90+
private function resolve(?array $source, array $args, ResolveInfo $info, ?string $rootClass = null, ?Operation $operation = null, mixed $body = null): mixed
9191
{
9292
// Handles relay nodes
9393
if (!$operation) {

src/Hydra/Serializer/DocumentationNormalizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ private function getHydraOperation(HttpOperation $operation, string $prefixedSho
313313

314314
if (null !== $inputClass) {
315315
$possibleValue = [];
316-
foreach ($operation->getInputFormats() as $mimeTypes) {
316+
foreach ($operation->getInputFormats() ?? [] as $mimeTypes) {
317317
foreach ($mimeTypes as $mimeType) {
318318
$possibleValue[] = $mimeType;
319319
}

src/Laravel/Controller/ApiPlatformController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private function getUriVariables(Request $request, HttpOperation $operation): ar
103103
{
104104
$uriVariables = [];
105105
foreach ($operation->getUriVariables() ?? [] as $parameterName => $_) {
106-
$parameter = $request->route($parameterName);
106+
$parameter = $request->route((string) $parameterName);
107107
if (\is_string($parameter) && ($format = $request->attributes->get('_format')) && str_contains($parameter, $format)) {
108108
$parameter = substr($parameter, 0, \strlen($parameter) - (\strlen($format) + 1));
109109
}

src/Laravel/Exception/ErrorHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public function render($request, \Throwable $exception)
7777
$operation = null;
7878
foreach ($resourceCollection as $resource) {
7979
foreach ($resource->getOperations() as $op) {
80-
foreach ($op->getOutputFormats() as $key => $value) {
80+
foreach ($op->getOutputFormats() ?? [] as $key => $value) {
8181
if ($key === $format) {
8282
$operation = $op;
8383
break 3;

src/Metadata/ApiProperty.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ final class ApiProperty
4848
* @param bool|null $push https://api-platform.com/docs/core/push-relations/
4949
* @param string|\Stringable|null $security https://api-platform.com/docs/core/security
5050
* @param string|\Stringable|null $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization
51-
* @param string[] $types the RDF types of this property
52-
* @param string[] $iris
53-
* @param LegacyType[] $builtinTypes
51+
* @param string[]|null $types the RDF types of this property
52+
* @param string[]|null $iris
53+
* @param LegacyType[]|null $builtinTypes
5454
* @param string|null $uriTemplate (experimental) whether to return the subRessource collection IRI instead of an iterable of IRI
5555
* @param string|null $property The property name
5656
* @param Context|Groups|Ignore|SerializedName|SerializedPath|MaxDepth|array<array-key, Context|Groups|Ignore|SerializedName|SerializedPath|MaxDepth> $serialize Serializer attributes
57-
* @param Type $nativeType The internal PHP type
57+
* @param Type|null $nativeType The internal PHP type
5858
*/
5959
public function __construct(
6060
private ?string $description = null,
@@ -345,12 +345,12 @@ public function withIdentifier(bool $identifier): static
345345
return $self;
346346
}
347347

348-
public function getDefault()
348+
public function getDefault(): mixed
349349
{
350350
return $this->default;
351351
}
352352

353-
public function withDefault($default): static
353+
public function withDefault(mixed $default): static
354354
{
355355
$self = clone $this;
356356
$self->default = $default;
@@ -507,7 +507,7 @@ public function withTypes(array|string $types = []): static
507507
/**
508508
* deprecated since 4.2, use "getNativeType" instead.
509509
*
510-
* @return LegacyType[]
510+
* @return LegacyType[]|null
511511
*/
512512
public function getBuiltinTypes(): ?array
513513
{
@@ -587,6 +587,8 @@ public function withExtraProperties(array $extraProperties = []): static
587587

588588
/**
589589
* Gets IRI of this property.
590+
*
591+
* @return string[]|null
590592
*/
591593
public function getIris()
592594
{
@@ -609,7 +611,7 @@ public function withIris(string|array $iris): static
609611
/**
610612
* Whether to generate a skolem iri on anonymous resources.
611613
*/
612-
public function getGenId()
614+
public function getGenId(): ?bool
613615
{
614616
return $this->genId;
615617
}

src/Metadata/Extractor/XmlPropertyExtractor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ private function buildValues(\SimpleXMLElement $resource): array
110110
return $data;
111111
}
112112

113-
private function buildArrayValue(?\SimpleXMLElement $resource, string $key, mixed $default = null)
113+
private function buildArrayValue(?\SimpleXMLElement $resource, string $key): ?array
114114
{
115115
if (!isset($resource->{$key.'s'}->{$key})) {
116-
return $default;
116+
return null;
117117
}
118118

119119
return (array) $resource->{$key.'s'}->{$key};

src/Metadata/Extractor/YamlPropertyExtractor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ private function buildProperties(array $resourcesYaml): void
101101
}
102102
}
103103

104-
private function buildAttribute(array $resource, string $key, mixed $default = null)
104+
private function buildAttribute(array $resource, string $key): ?array
105105
{
106106
if (empty($resource[$key])) {
107-
return $default;
107+
return null;
108108
}
109109

110110
if (!\is_array($resource[$key])) {

src/Metadata/HttpOperation.php

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ class HttpOperation extends Operation
2929
public const METHOD_HEAD = 'HEAD';
3030
public const METHOD_OPTIONS = 'OPTIONS';
3131

32+
/** @var array<int|string, string|string[]>|null */
33+
protected $formats;
34+
/** @var array<int|string, string|string[]>|null */
35+
protected $inputFormats;
36+
/** @var array<int|string, string|string[]>|null */
37+
protected $outputFormats;
38+
3239
/**
3340
* @param string[]|null $types the RDF types of this property
3441
* @param array<int|string, string|string[]>|string|null $formats {@see https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation}
@@ -90,9 +97,9 @@ public function __construct(
9097
protected string $method = 'GET',
9198
protected ?string $uriTemplate = null,
9299
protected ?array $types = null,
93-
protected $formats = null,
94-
protected $inputFormats = null,
95-
protected $outputFormats = null,
100+
$formats = null,
101+
$inputFormats = null,
102+
$outputFormats = null,
96103
protected $uriVariables = null,
97104
protected ?string $routePrefix = null,
98105
protected ?string $routeName = null,
@@ -214,6 +221,10 @@ public function __construct(
214221
?bool $queryParameterValidationEnabled = null,
215222
array $extraProperties = [],
216223
) {
224+
$this->formats = (null === $formats || \is_array($formats)) ? $formats : [$formats];
225+
$this->inputFormats = (null === $inputFormats || \is_array($inputFormats)) ? $inputFormats : [$inputFormats];
226+
$this->outputFormats = (null === $outputFormats || \is_array($outputFormats)) ? $outputFormats : [$outputFormats];
227+
217228
parent::__construct(
218229
shortName: $shortName,
219230
class: $class,
@@ -287,7 +298,7 @@ public function getUriTemplate(): ?string
287298
return $this->uriTemplate;
288299
}
289300

290-
public function withUriTemplate(?string $uriTemplate = null)
301+
public function withUriTemplate(?string $uriTemplate = null): static
291302
{
292303
$self = clone $this;
293304
$self->uriTemplate = $uriTemplate;
@@ -311,45 +322,66 @@ public function withTypes($types): static
311322
return $self;
312323
}
313324

325+
/**
326+
* @return array<int|string, string|string[]>|null
327+
*/
314328
public function getFormats()
315329
{
316330
return $this->formats;
317331
}
318332

333+
/**
334+
* @param array<int|string, string|string[]>|string|null $formats
335+
*/
319336
public function withFormats($formats = null): static
320337
{
321338
$self = clone $this;
322-
$self->formats = $formats;
339+
$self->formats = (null === $formats || \is_array($formats)) ? $formats : [$formats];
323340

324341
return $self;
325342
}
326343

344+
/**
345+
* @return array<int|string, string|string[]>|null
346+
*/
327347
public function getInputFormats()
328348
{
329349
return $this->inputFormats;
330350
}
331351

352+
/**
353+
* @param array<int|string, string|string[]>|string|null $inputFormats
354+
*/
332355
public function withInputFormats($inputFormats = null): static
333356
{
334357
$self = clone $this;
335-
$self->inputFormats = $inputFormats;
358+
$self->inputFormats = (null === $inputFormats || \is_array($inputFormats)) ? $inputFormats : [$inputFormats];
336359

337360
return $self;
338361
}
339362

363+
/**
364+
* @return array<int|string, string|string[]>|null
365+
*/
340366
public function getOutputFormats()
341367
{
342368
return $this->outputFormats;
343369
}
344370

371+
/**
372+
* @param array<int|string, string|string[]>|string|null $outputFormats
373+
*/
345374
public function withOutputFormats($outputFormats = null): static
346375
{
347376
$self = clone $this;
348-
$self->outputFormats = $outputFormats;
377+
$self->outputFormats = (null === $outputFormats || \is_array($outputFormats)) ? $outputFormats : [$outputFormats];
349378

350379
return $self;
351380
}
352381

382+
/**
383+
* @return array<string, mixed>|array<int, Link>|list<string>|null
384+
*/
353385
public function getUriVariables()
354386
{
355387
return $this->uriVariables;

0 commit comments

Comments
 (0)