diff --git a/composer.json b/composer.json index 08f5b685..5b5438ff 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,10 @@ "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", "phpunit/phpunit": "^9.5", + "psr/container": "1.0 || 1.1.1", "symfony/config": "^4.2 || ^5.0", "symfony/console": "^4.0 || ^5.0", + "symfony/dependency-injection": "^4.0 || ^5.0", "symfony/form": "^4.0 || ^5.0", "symfony/framework-bundle": "^4.4 || ^5.0", "symfony/http-foundation": "^5.1", diff --git a/src/Type/Symfony/ServiceDynamicReturnTypeExtension.php b/src/Type/Symfony/ServiceDynamicReturnTypeExtension.php index 04608c17..cd3d2a46 100644 --- a/src/Type/Symfony/ServiceDynamicReturnTypeExtension.php +++ b/src/Type/Symfony/ServiceDynamicReturnTypeExtension.php @@ -8,11 +8,14 @@ use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\ShouldNotHappenException; use PHPStan\Symfony\Configuration; +use PHPStan\Symfony\ParameterMap; +use PHPStan\Symfony\ServiceDefinition; use PHPStan\Symfony\ServiceMap; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\DynamicMethodReturnTypeExtension; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use function in_array; final class ServiceDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension @@ -27,11 +30,20 @@ final class ServiceDynamicReturnTypeExtension implements DynamicMethodReturnType /** @var ServiceMap */ private $serviceMap; - public function __construct(string $className, Configuration $configuration, ServiceMap $symfonyServiceMap) + /** @var ParameterBag */ + private $parameterBag; + + public function __construct( + string $className, + Configuration $configuration, + ServiceMap $symfonyServiceMap, + ParameterMap $symfonyParameterMap + ) { $this->className = $className; $this->constantHassers = $configuration->hasConstantHassers(); $this->serviceMap = $symfonyServiceMap; + $this->parameterBag = $this->createParameterBag($symfonyParameterMap); } public function getClass(): string @@ -70,7 +82,7 @@ private function getGetTypeFromMethodCall( if ($serviceId !== null) { $service = $this->serviceMap->getService($serviceId); if ($service !== null && (!$service->isSynthetic() || $service->getClass() !== null)) { - return new ObjectType($service->getClass() ?? $serviceId); + return new ObjectType($this->determineServiceClass($service) ?? $serviceId); } } @@ -97,4 +109,20 @@ private function getHasTypeFromMethodCall( return $returnType; } + private function determineServiceClass(ServiceDefinition $service): ?string + { + return $this->parameterBag->resolveValue($service->getClass()); + } + + private function createParameterBag(ParameterMap $symfonyParameterMap): ParameterBag + { + $parameters = []; + + foreach ($symfonyParameterMap->getParameters() as $parameterDefinition) { + $parameters[$parameterDefinition->getKey()] = $parameterDefinition->getValue(); + } + + return new ParameterBag($parameters); + } + } diff --git a/tests/Type/Symfony/container.xml b/tests/Type/Symfony/container.xml index e6f8f03b..992289f2 100644 --- a/tests/Type/Symfony/container.xml +++ b/tests/Type/Symfony/container.xml @@ -1,6 +1,7 @@ + Foo abcdef 123 123 @@ -51,6 +52,8 @@ + + diff --git a/tests/Type/Symfony/data/ExampleAbstractController.php b/tests/Type/Symfony/data/ExampleAbstractController.php index 6dc6ef7e..6fdb281d 100644 --- a/tests/Type/Symfony/data/ExampleAbstractController.php +++ b/tests/Type/Symfony/data/ExampleAbstractController.php @@ -13,6 +13,8 @@ final class ExampleAbstractController extends AbstractController public function services(): void { assertType('Foo', $this->get('foo')); + assertType('Foo', $this->get('parameterised_foo')); + assertType('Foo\Bar', $this->get('parameterised_bar')); assertType('Synthetic', $this->get('synthetic')); assertType('object', $this->get('bar')); assertType('object', $this->get(doFoo())); diff --git a/tests/Type/Symfony/data/ExampleController.php b/tests/Type/Symfony/data/ExampleController.php index 8cd0c93a..b09cc25d 100644 --- a/tests/Type/Symfony/data/ExampleController.php +++ b/tests/Type/Symfony/data/ExampleController.php @@ -13,6 +13,8 @@ final class ExampleController extends Controller public function services(): void { assertType('Foo', $this->get('foo')); + assertType('Foo', $this->get('parameterised_foo')); + assertType('Foo\Bar', $this->get('parameterised_bar')); assertType('Synthetic', $this->get('synthetic')); assertType('object', $this->get('bar')); assertType('object', $this->get(doFoo()));

AltStyle によって変換されたページ (->オリジナル) /