Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d6a29ae

Browse filesBrowse files
bug #44578 [PropertyInfo] Fix phpstan extractor issues (ostrolucky)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [PropertyInfo] Fix phpstan extractor issues | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #44491 | License | MIT | Doc PR | Since this crashes denormalization for codebase that was upgraded from 5.3 to 5.4, I am classifying this as a bugfix. This PR fixes 2 issues. One is with docblocks like `/** `@var` Foo::*|null */`, where Extractor returns `null` only and afterwards Serializer fails to accept anything else. Second is `/** `@var` non-empty-array<...> */` where extractor doesn't recognize that `non-empty-array` is still an array and afterwards Serializer fails complaining that `array` is not an `non-empty-array` Commits ------- 0302128 [PropertyInfo] Fix phpstan extractor issues
2 parents d17ae34 + 0302128 commit d6a29ae
Copy full SHA for d6a29ae

File tree

4 files changed

+42
-1
lines changed
Filter options

4 files changed

+42
-1
lines changed

‎src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ public function constructorTypesProvider()
355355
/**
356356
* @dataProvider unionTypesProvider
357357
*/
358-
public function testExtractorUnionTypes(string $property, array $types)
358+
public function testExtractorUnionTypes(string $property, ?array $types)
359359
{
360360
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DummyUnionType', $property));
361361
}
@@ -368,6 +368,8 @@ public function unionTypesProvider(): array
368368
['c', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
369369
['d', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])])]],
370370
['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, true, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING, false, null, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
371+
['f', null],
372+
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
371373
];
372374
}
373375

‎src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
*/
1717
class DummyUnionType
1818
{
19+
private const TYPE_A = 'a';
20+
private const TYPE_B = 'b';
21+
1922
/**
2023
* @var string|int
2124
*/
@@ -40,4 +43,14 @@ class DummyUnionType
4043
* @var (Dummy<array<mixed, string>, (int | (string<DefaultValue>)[])> | ParentDummy | null)
4144
*/
4245
public $e;
46+
47+
/**
48+
* @var self::TYPE_*|null
49+
*/
50+
public $f;
51+
52+
/**
53+
* @var non-empty-array<string|int>
54+
*/
55+
public $g;
4356
}

‎src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
2020
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
2121
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
22+
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
2223
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
2324
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
2425
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
@@ -102,6 +103,10 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
102103
if ($node instanceof UnionTypeNode) {
103104
$types = [];
104105
foreach ($node->types as $type) {
106+
if ($type instanceof ConstTypeNode) {
107+
// It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment
108+
return [];
109+
}
105110
foreach ($this->extractTypes($type, $nameScope) as $subType) {
106111
$types[] = $subType;
107112
}
@@ -160,7 +165,10 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
160165
case 'integer':
161166
return [new Type(Type::BUILTIN_TYPE_INT)];
162167
case 'list':
168+
case 'non-empty-list':
163169
return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))];
170+
case 'non-empty-array':
171+
return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)];
164172
case 'mixed':
165173
return []; // mixed seems to be ignored in all other extractors
166174
case 'parent':

‎src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
namespace Symfony\Component\Serializer\Tests\Normalizer;
1313

1414
use Doctrine\Common\Annotations\AnnotationReader;
15+
use PHPStan\PhpDocParser\Parser\PhpDocParser;
1516
use PHPUnit\Framework\TestCase;
1617
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
18+
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
1719
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
1820
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
1921
use Symfony\Component\Serializer\Exception\LogicException;
@@ -721,6 +723,22 @@ public function testAcceptJsonNumber()
721723
$this->assertSame(10.0, $serializer->denormalize(['number' => 10], JsonNumber::class, 'jsonld')->number);
722724
}
723725

726+
public function testDoesntHaveIssuesWithUnionConstTypes()
727+
{
728+
if (!class_exists(PhpStanExtractor::class) || !class_exists(PhpDocParser::class)) {
729+
$this->markTestSkipped('phpstan/phpdoc-parser required for this test');
730+
}
731+
732+
$extractor = new PropertyInfoExtractor([], [new PhpStanExtractor(), new PhpDocExtractor(), new ReflectionExtractor()]);
733+
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
734+
$serializer = new Serializer([new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer]);
735+
736+
$this->assertSame('bar', $serializer->denormalize(['foo' => 'bar'], \get_class(new class() {
737+
/** @var self::*|null */
738+
public $foo;
739+
}))->foo);
740+
}
741+
724742
public function testExtractAttributesRespectsFormat()
725743
{
726744
$normalizer = new FormatAndContextAwareNormalizer();

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.