Merge pull request #2150 from rectorphp/container-after-boot

phpstan - add getContainer() after boot()
This commit is contained in:
Tomáš Votruba 2019-10-13 01:11:05 +02:00 committed by GitHub
commit a323fff8d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 0 deletions

View File

@ -2,3 +2,7 @@ services:
-
class: Rector\NodeTypeResolver\Type\TypeExtension\StaticContainerGetDynamicMethodReturnTypeExtension
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]
-
class: Rector\NodeTypeResolver\Type\TypeExtension\KernelGetContainerAfterBootReturnTypeExtension
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]

View File

@ -0,0 +1,56 @@
<?php declare(strict_types=1);
namespace Rector\NodeTypeResolver\Type\TypeExtension;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Symfony\Component\HttpKernel\Kernel;
final class KernelGetContainerAfterBootReturnTypeExtension implements DynamicMethodReturnTypeExtension
{
public function getClass(): string
{
return Kernel::class;
}
public function isMethodSupported(MethodReflection $methodReflection): bool
{
return $methodReflection->getName() === 'getContainer';
}
public function getTypeFromMethodCall(
MethodReflection $methodReflection,
MethodCall $methodCall,
Scope $scope
): Type {
$returnType = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
if ($this->isCalledAfterBoot($scope, $methodCall) === false) {
return $returnType;
}
if ($returnType instanceof UnionType) {
foreach ($returnType->getTypes() as $singleType) {
if ($singleType instanceof ObjectType) {
return $singleType;
}
}
}
return $returnType;
}
private function isCalledAfterBoot(Scope $scope, MethodCall $methodCall): bool
{
$kernelBootMethodCall = new MethodCall($methodCall->var, 'boot');
return ! $scope->getType($kernelBootMethodCall) instanceof ErrorType;
}
}