Skip to content

Commit d292842

Browse files
committed
Add support for Serializer::deserialize
1 parent a364099 commit d292842

6 files changed

+90
-2
lines changed

Diff for: composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"slevomat/coding-standard": "^4.5.2",
3333
"phpstan/phpstan-phpunit": "^0.11",
3434
"symfony/framework-bundle": "^3.0 || ^4.0",
35-
"squizlabs/php_codesniffer": "^3.3.2"
35+
"squizlabs/php_codesniffer": "^3.3.2",
36+
"symfony/serializer": "^3|^4"
3637
},
3738
"conflict": {
3839
"symfony/framework-bundle": "<3.0"

Diff for: extension.neon

+5
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,8 @@ services:
4545
-
4646
class: PHPStan\Type\Symfony\HeaderBagDynamicReturnTypeExtension
4747
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
48+
49+
# SerializerInterface::deserialize() return type
50+
-
51+
class: PHPStan\Type\Symfony\SerializerInterfaceDynamicReturnTypeExtension
52+
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Symfony;
4+
5+
use PhpParser\Node\Expr\MethodCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\MethodReflection;
8+
use PHPStan\Type\ArrayType;
9+
use PHPStan\Type\Constant\ConstantStringType;
10+
use PHPStan\Type\DynamicMethodReturnTypeExtension;
11+
use PHPStan\Type\MixedType;
12+
use PHPStan\Type\ObjectType;
13+
use PHPStan\Type\Type;
14+
15+
class SerializerInterfaceDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
16+
{
17+
18+
public function getClass(): string
19+
{
20+
return 'Symfony\Component\Serializer\SerializerInterface';
21+
}
22+
23+
public function isMethodSupported(MethodReflection $methodReflection): bool
24+
{
25+
return $methodReflection->getName() === 'deserialize';
26+
}
27+
28+
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
29+
{
30+
$argType = $scope->getType($methodCall->args[1]->value);
31+
if (!$argType instanceof ConstantStringType) {
32+
return new MixedType();
33+
}
34+
35+
$objectName = $argType->getValue();
36+
37+
if (substr($objectName, -2) === '[]') {
38+
// The key type is determined by the data
39+
return new ArrayType(new MixedType(false), new ObjectType(substr($objectName, 0, -2)));
40+
}
41+
42+
return new ObjectType($objectName);
43+
}
44+
45+
}

Diff for: tests/Symfony/NeonTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function testExtensionNeon(): void
4040
], $container->getParameters());
4141

4242
self::assertCount(2, $container->findByTag('phpstan.rules.rule'));
43-
self::assertCount(5, $container->findByTag('phpstan.broker.dynamicMethodReturnTypeExtension'));
43+
self::assertCount(6, $container->findByTag('phpstan.broker.dynamicMethodReturnTypeExtension'));
4444
self::assertCount(3, $container->findByTag('phpstan.typeSpecifier.methodTypeSpecifyingExtension'));
4545
self::assertInstanceOf(ServiceMap::class, $container->getByType(ServiceMap::class));
4646
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Symfony;
4+
5+
use Iterator;
6+
7+
final class SerializerInterfaceDynamicReturnTypeExtensionTest extends ExtensionTestCase
8+
{
9+
10+
/**
11+
* @dataProvider getContentProvider
12+
*/
13+
public function testGetContent(string $expression, string $type): void
14+
{
15+
$this->processFile(
16+
__DIR__ . '/serializer.php',
17+
$expression,
18+
$type,
19+
new SerializerInterfaceDynamicReturnTypeExtension()
20+
);
21+
}
22+
23+
public function getContentProvider(): Iterator
24+
{
25+
yield ['$first', 'Bar'];
26+
yield ['$second', 'array<Bar>'];
27+
}
28+
29+
}

Diff for: tests/Type/Symfony/serializer.php

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types = 1);
2+
3+
$serializer = new \Symfony\Component\Serializer\Serializer();
4+
5+
$first = $serializer->deserialize('bar', 'Bar', 'format');
6+
$second = $serializer->deserialize('bar', 'Bar[]', 'format');
7+
8+
die;

0 commit comments

Comments
 (0)