From d4619ca475512fec05977ca589627b6ffdc017cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Thu, 28 Mar 2019 09:30:04 +0100 Subject: [PATCH 1/3] Add EnvelopeReturnTypeExtension for symfony/messenger --- composer.json | 3 +- .../Symfony/EnvelopeReturnTypeExtension.php | 47 +++++++++++++++++++ .../EnvelopeReturnTypeExtensionTest.php | 32 +++++++++++++ tests/Type/Symfony/envelope_all.php | 9 ++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/Type/Symfony/EnvelopeReturnTypeExtension.php create mode 100644 tests/Type/Symfony/EnvelopeReturnTypeExtensionTest.php create mode 100644 tests/Type/Symfony/envelope_all.php diff --git a/composer.json b/composer.json index 4126f9e2..4118192a 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ "phpstan/phpstan-phpunit": "^0.11", "symfony/framework-bundle": "^3.0 || ^4.0", "squizlabs/php_codesniffer": "^3.3.2", - "symfony/serializer": "^3|^4" + "symfony/serializer": "^3|^4", + "symfony/messenger": "^4.2" }, "conflict": { "symfony/framework-bundle": "<3.0" diff --git a/src/Type/Symfony/EnvelopeReturnTypeExtension.php b/src/Type/Symfony/EnvelopeReturnTypeExtension.php new file mode 100644 index 00000000..debc01d5 --- /dev/null +++ b/src/Type/Symfony/EnvelopeReturnTypeExtension.php @@ -0,0 +1,47 @@ +getName() === 'all'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type + { + if (count($methodCall->args) === 0) { + return new ArrayType(new MixedType(), new ArrayType(new MixedType(), new ObjectType(StampInterface::class))); + } + + $argType = $scope->getType($methodCall->args[0]->value); + if (!$argType instanceof ConstantStringType) { + return new ArrayType(new MixedType(), new ObjectType(StampInterface::class)); + } + + return new ArrayType(new MixedType(), new ObjectType($argType->getValue())); + } + +} diff --git a/tests/Type/Symfony/EnvelopeReturnTypeExtensionTest.php b/tests/Type/Symfony/EnvelopeReturnTypeExtensionTest.php new file mode 100644 index 00000000..0a3f9a2b --- /dev/null +++ b/tests/Type/Symfony/EnvelopeReturnTypeExtensionTest.php @@ -0,0 +1,32 @@ +processFile( + __DIR__ . '/envelope_all.php', + $expression, + $type, + new EnvelopeReturnTypeExtension() + ); + } + + public function getProvider(): Iterator + { + yield ['$test1', 'array<' . ReceivedStamp::class . '>']; + yield ['$test2', 'array<' . StampInterface::class . '>']; + yield ['$test3', 'array>']; + } + +} diff --git a/tests/Type/Symfony/envelope_all.php b/tests/Type/Symfony/envelope_all.php new file mode 100644 index 00000000..f2bd3ec4 --- /dev/null +++ b/tests/Type/Symfony/envelope_all.php @@ -0,0 +1,9 @@ +all(\Symfony\Component\Messenger\Stamp\ReceivedStamp::class); +$test2 = $envelope->all(random_bytes(1)); +$test3 = $envelope->all(); + +die; From 6eaf5a9cb08a390878d04a6b49e682af28e660b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Mon, 1 Apr 2019 08:37:25 +0200 Subject: [PATCH 2/3] Update EnvelopeReturnTypeExtension.php --- src/Type/Symfony/EnvelopeReturnTypeExtension.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Type/Symfony/EnvelopeReturnTypeExtension.php b/src/Type/Symfony/EnvelopeReturnTypeExtension.php index debc01d5..bf0712fc 100644 --- a/src/Type/Symfony/EnvelopeReturnTypeExtension.php +++ b/src/Type/Symfony/EnvelopeReturnTypeExtension.php @@ -11,7 +11,6 @@ use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; -use Symfony\Component\Messenger\Stamp\StampInterface; final class EnvelopeReturnTypeExtension implements DynamicMethodReturnTypeExtension { @@ -33,12 +32,12 @@ public function getTypeFromMethodCall( ): Type { if (count($methodCall->args) === 0) { - return new ArrayType(new MixedType(), new ArrayType(new MixedType(), new ObjectType(StampInterface::class))); + return new ArrayType(new MixedType(), new ArrayType(new MixedType(), new ObjectType('Symfony\Component\Messenger\Stamp\StampInterface'))); } $argType = $scope->getType($methodCall->args[0]->value); if (!$argType instanceof ConstantStringType) { - return new ArrayType(new MixedType(), new ObjectType(StampInterface::class)); + return new ArrayType(new MixedType(), new ObjectType('Symfony\Component\Messenger\Stamp\StampInterface')); } return new ArrayType(new MixedType(), new ObjectType($argType->getValue())); From eb878cf5dc7ec2f6043cbab891bbb91ede9b8321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Unger?= Date: Mon, 1 Apr 2019 09:48:54 +0200 Subject: [PATCH 3/3] Fix Nette deprecations & extension test case virtual nodes --- extension.neon | 25 ++++++++++++++---------- tests/Symfony/NeonTest.php | 2 +- tests/Type/Symfony/ExtensionTestCase.php | 7 +++++-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/extension.neon b/extension.neon index 07424feb..ca7288f2 100644 --- a/extension.neon +++ b/extension.neon @@ -12,41 +12,46 @@ services: class: PHPStan\Symfony\ServiceMapFactory factory: PHPStan\Symfony\XmlServiceMapFactory(%symfony.container_xml_path%) - - class: @symfony.serviceMapFactory::create() + factory: @symfony.serviceMapFactory::create() # ControllerTrait::get()/has() return type - - class: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Component\DependencyInjection\ContainerInterface, %symfony.constant_hassers%) + factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Component\DependencyInjection\ContainerInterface, %symfony.constant_hassers%) tags: [phpstan.broker.dynamicMethodReturnTypeExtension] - - class: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller, %symfony.constant_hassers%) + factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller, %symfony.constant_hassers%) tags: [phpstan.broker.dynamicMethodReturnTypeExtension] - - class: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Bundle\FrameworkBundle\Controller\AbstractController, %symfony.constant_hassers%) + factory: PHPStan\Type\Symfony\ServiceDynamicReturnTypeExtension(Symfony\Bundle\FrameworkBundle\Controller\AbstractController, %symfony.constant_hassers%) tags: [phpstan.broker.dynamicMethodReturnTypeExtension] # ControllerTrait::has() type specification - - class: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Component\DependencyInjection\ContainerInterface) + factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Component\DependencyInjection\ContainerInterface) tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension] - - class: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller) + factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Bundle\FrameworkBundle\Controller\Controller) tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension] - - class: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Bundle\FrameworkBundle\Controller\AbstractController) + factory: PHPStan\Type\Symfony\ServiceTypeSpecifyingExtension(Symfony\Bundle\FrameworkBundle\Controller\AbstractController) tags: [phpstan.typeSpecifier.methodTypeSpecifyingExtension] # Request::getContent() return type - - class: PHPStan\Type\Symfony\RequestDynamicReturnTypeExtension + factory: PHPStan\Type\Symfony\RequestDynamicReturnTypeExtension tags: [phpstan.broker.dynamicMethodReturnTypeExtension] # HeaderBag::get() return type - - class: PHPStan\Type\Symfony\HeaderBagDynamicReturnTypeExtension + factory: PHPStan\Type\Symfony\HeaderBagDynamicReturnTypeExtension tags: [phpstan.broker.dynamicMethodReturnTypeExtension] # SerializerInterface::deserialize() return type - - class: PHPStan\Type\Symfony\SerializerInterfaceDynamicReturnTypeExtension + factory: PHPStan\Type\Symfony\SerializerInterfaceDynamicReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + + # Envelope::all() return type + - + factory: PHPStan\Type\Symfony\EnvelopeReturnTypeExtension tags: [phpstan.broker.dynamicMethodReturnTypeExtension] diff --git a/tests/Symfony/NeonTest.php b/tests/Symfony/NeonTest.php index e14ef8f2..a189b043 100644 --- a/tests/Symfony/NeonTest.php +++ b/tests/Symfony/NeonTest.php @@ -40,7 +40,7 @@ public function testExtensionNeon(): void ], $container->getParameters()); self::assertCount(2, $container->findByTag('phpstan.rules.rule')); - self::assertCount(6, $container->findByTag('phpstan.broker.dynamicMethodReturnTypeExtension')); + self::assertCount(7, $container->findByTag('phpstan.broker.dynamicMethodReturnTypeExtension')); self::assertCount(3, $container->findByTag('phpstan.typeSpecifier.methodTypeSpecifyingExtension')); self::assertInstanceOf(ServiceMap::class, $container->getByType(ServiceMap::class)); } diff --git a/tests/Type/Symfony/ExtensionTestCase.php b/tests/Type/Symfony/ExtensionTestCase.php index c0c8ec93..a1cef2bf 100644 --- a/tests/Type/Symfony/ExtensionTestCase.php +++ b/tests/Type/Symfony/ExtensionTestCase.php @@ -10,7 +10,7 @@ use PHPStan\Broker\AnonymousClassNameHelper; use PHPStan\Cache\Cache; use PHPStan\File\FileHelper; -use PHPStan\Node\InClassMethodNode; +use PHPStan\Node\VirtualNode; use PHPStan\PhpDoc\PhpDocStringResolver; use PHPStan\PhpDoc\TypeNodeResolver; use PHPStan\Testing\TestCase; @@ -61,7 +61,10 @@ protected function processFile( $parser->parseFile($file), $this->createScopeFactory($broker, $typeSpecifier)->create(ScopeContext::create($file)), function (Node $node, Scope $scope) use ($expression, $type, &$run): void { - if ((new Standard())->prettyPrint([$node instanceof InClassMethodNode ? $node->getOriginalNode() : $node]) !== 'die') { + if ($node instanceof VirtualNode) { + return; + } + if ((new Standard())->prettyPrint([$node]) !== 'die') { return; } /** @var \PhpParser\Node\Stmt\Expression $expNode */