Skip to content

Commit

Permalink
[PropertyInfo] Fix phpstan extractor issues
Browse files Browse the repository at this point in the history
  • Loading branch information
ostrolucky authored and nicolas-grekas committed Dec 25, 2021
1 parent 807672d commit 0302128
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ public function constructorTypesProvider()
/**
* @dataProvider unionTypesProvider
*/
public function testExtractorUnionTypes(string $property, array $types)
public function testExtractorUnionTypes(string $property, ?array $types)
{
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DummyUnionType', $property));
}
Expand All @@ -368,6 +368,8 @@ public function unionTypesProvider(): array
['c', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
['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)])])]],
['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)]],
['f', null],
['g', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/
class DummyUnionType
{
private const TYPE_A = 'a';
private const TYPE_B = 'b';

/**
* @var string|int
*/
Expand All @@ -40,4 +43,14 @@ class DummyUnionType
* @var (Dummy<array<mixed, string>, (int | (string<DefaultValue>)[])> | ParentDummy | null)
*/
public $e;

/**
* @var self::TYPE_*|null
*/
public $f;

/**
* @var non-empty-array<string|int>
*/
public $g;
}
8 changes: 8 additions & 0 deletions src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
Expand Down Expand Up @@ -102,6 +103,10 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
if ($node instanceof UnionTypeNode) {
$types = [];
foreach ($node->types as $type) {
if ($type instanceof ConstTypeNode) {
// It's safer to fall back to other extractors here, as resolving const types correctly is not easy at the moment
return [];
}
foreach ($this->extractTypes($type, $nameScope) as $subType) {
$types[] = $subType;
}
Expand Down Expand Up @@ -160,7 +165,10 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
case 'integer':
return [new Type(Type::BUILTIN_TYPE_INT)];
case 'list':
case 'non-empty-list':
return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT))];
case 'non-empty-array':
return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)];
case 'mixed':
return []; // mixed seems to be ignored in all other extractors
case 'parent':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
namespace Symfony\Component\Serializer\Tests\Normalizer;

use Doctrine\Common\Annotations\AnnotationReader;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Exception\LogicException;
Expand Down Expand Up @@ -721,6 +723,22 @@ public function testAcceptJsonNumber()
$this->assertSame(10.0, $serializer->denormalize(['number' => 10], JsonNumber::class, 'jsonld')->number);
}

public function testDoesntHaveIssuesWithUnionConstTypes()
{
if (!class_exists(PhpStanExtractor::class) || !class_exists(PhpDocParser::class)) {
$this->markTestSkipped('phpstan/phpdoc-parser required for this test');
}

$extractor = new PropertyInfoExtractor([], [new PhpStanExtractor(), new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
$serializer = new Serializer([new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer]);

$this->assertSame('bar', $serializer->denormalize(['foo' => 'bar'], \get_class(new class() {
/** @var self::*|null */
public $foo;
}))->foo);
}

public function testExtractAttributesRespectsFormat()
{
$normalizer = new FormatAndContextAwareNormalizer();
Expand Down

0 comments on commit 0302128

Please sign in to comment.