mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-02 01:10:53 +00:00
symplify PropertyTypeResolver
This commit is contained in:
parent
d91cf73b01
commit
45ca92729d
|
@ -5,10 +5,12 @@ namespace Rector\NodeTypeResolver;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Broker\Broker;
|
||||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\Node\TypeAttribute;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeToStringResolver;
|
||||
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
|
||||
|
||||
final class NodeTypeResolver
|
||||
{
|
||||
|
@ -22,9 +24,24 @@ final class NodeTypeResolver
|
|||
*/
|
||||
private $typeToStringResolver;
|
||||
|
||||
public function __construct(TypeToStringResolver $typeToStringResolver)
|
||||
{
|
||||
/**
|
||||
* @var Broker
|
||||
*/
|
||||
private $broker;
|
||||
|
||||
/**
|
||||
* @var ClassReflectionTypesResolver
|
||||
*/
|
||||
private $classReflectionTypesResolver;
|
||||
|
||||
public function __construct(
|
||||
TypeToStringResolver $typeToStringResolver,
|
||||
Broker $broker,
|
||||
ClassReflectionTypesResolver $classReflectionTypesResolver
|
||||
) {
|
||||
$this->typeToStringResolver = $typeToStringResolver;
|
||||
$this->broker = $broker;
|
||||
$this->classReflectionTypesResolver = $classReflectionTypesResolver;
|
||||
}
|
||||
|
||||
public function addPerNodeTypeResolver(PerNodeTypeResolverInterface $perNodeTypeResolver): void
|
||||
|
@ -43,6 +60,24 @@ final class NodeTypeResolver
|
|||
* @return string[]
|
||||
*/
|
||||
public function resolve(Node $node): array
|
||||
{
|
||||
$types = $this->resolveFirstTypes($node);
|
||||
if ($types === []) {
|
||||
return $types;
|
||||
}
|
||||
|
||||
// complete parent types - parent classes, interfaces and traits
|
||||
foreach ($types as $type) {
|
||||
$types += $this->classReflectionTypesResolver->resolve($this->broker->getClass($type));
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveFirstTypes(Node $node): array
|
||||
{
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $node->getAttribute(TypeAttribute::SCOPE);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Rector\NodeTypeResolver;
|
||||
|
||||
use PHPStan\Broker\Broker;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeToStringResolver;
|
||||
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -26,7 +28,14 @@ final class NodeTypeResolverFactory
|
|||
{
|
||||
/** @var TypeToStringResolver $typeToStringResolver */
|
||||
$typeToStringResolver = $this->container->get(TypeToStringResolver::class);
|
||||
$nodeTypeResolver = new NodeTypeResolver($typeToStringResolver);
|
||||
|
||||
/** @var Broker $broker */
|
||||
$broker = $this->container->get(Broker::class);
|
||||
|
||||
/** @var ClassReflectionTypesResolver $classReflectionTypesResolver */
|
||||
$classReflectionTypesResolver = $this->container->get(ClassReflectionTypesResolver::class);
|
||||
|
||||
$nodeTypeResolver = new NodeTypeResolver($typeToStringResolver, $broker, $classReflectionTypesResolver);
|
||||
|
||||
foreach ($this->container->getServiceIds() as $serviceId) {
|
||||
if (! is_a($serviceId, PerNodeTypeResolverInterface::class, true)) {
|
||||
|
|
|
@ -3,46 +3,20 @@
|
|||
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\Broker\Broker;
|
||||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\TypeAttribute;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
|
||||
final class PropertyTypeResolver implements PerNodeTypeResolverInterface
|
||||
final class PropertyTypeResolver implements PerNodeTypeResolverInterface, NodeTypeResolverAwareInterface
|
||||
{
|
||||
/**
|
||||
* @var ClassReflectionTypesResolver
|
||||
* @var NodeTypeResolver
|
||||
*/
|
||||
private $classReflectionTypesResolver;
|
||||
|
||||
/**
|
||||
* @var DocBlockAnalyzer
|
||||
*/
|
||||
private $docBlockAnalyzer;
|
||||
|
||||
/**
|
||||
* @var Broker
|
||||
*/
|
||||
private $broker;
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
ClassReflectionTypesResolver $classReflectionTypesResolver,
|
||||
DocBlockAnalyzer $docBlockAnalyzer,
|
||||
Broker $broker,
|
||||
TypeAnalyzer $typeAnalyzer
|
||||
) {
|
||||
$this->classReflectionTypesResolver = $classReflectionTypesResolver;
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
$this->broker = $broker;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
private $nodeTypeResolver;
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
|
@ -58,39 +32,15 @@ final class PropertyTypeResolver implements PerNodeTypeResolverInterface
|
|||
*/
|
||||
public function resolve(Node $propertyNode): array
|
||||
{
|
||||
// doc
|
||||
$propertyTypes = $this->docBlockAnalyzer->getVarTypes($propertyNode);
|
||||
if ($propertyTypes === []) {
|
||||
return [];
|
||||
}
|
||||
// fake property to local PropertyFetch → PHPStan understand that
|
||||
$propertyFetchNode = new PropertyFetch(new Variable('this'), (string) $propertyNode->props[0]->name);
|
||||
$propertyFetchNode->setAttribute(TypeAttribute::SCOPE, $propertyNode->getAttribute(TypeAttribute::SCOPE));
|
||||
|
||||
$propertyTypes = $this->filterOutScalarTypes($propertyTypes);
|
||||
|
||||
foreach ($propertyTypes as $propertyType) {
|
||||
$propertyClassReflection = $this->broker->getClass($propertyType);
|
||||
$propertyTypes += $this->classReflectionTypesResolver->resolve($propertyClassReflection);
|
||||
}
|
||||
|
||||
return $propertyTypes;
|
||||
return $this->nodeTypeResolver->resolve($propertyFetchNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $propertyTypes
|
||||
* @return string[]
|
||||
*/
|
||||
private function filterOutScalarTypes(array $propertyTypes): array
|
||||
public function setNodeTypeResolver(NodeTypeResolver $nodeTypeResolver): void
|
||||
{
|
||||
foreach ($propertyTypes as $key => $type) {
|
||||
if (! $this->typeAnalyzer->isPhpReservedType($type)) {
|
||||
continue;
|
||||
}
|
||||
unset($propertyTypes[$key]);
|
||||
}
|
||||
|
||||
if ($propertyTypes === ['null']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $propertyTypes;
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\PropertyTypeResolver
|
|||
use Iterator;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\AbstractNodeTypeResolverTest;
|
||||
use Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\PropertyTypeResolver\Source\ClassThatExtendsHtml;
|
||||
use Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\PropertyTypeResolver\Source\Html;
|
||||
|
||||
/**
|
||||
|
@ -25,5 +26,6 @@ final class PropertyTypeResolverTest extends AbstractNodeTypeResolverTest
|
|||
public function provideData(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Source/ClassWithProperties.php', 0, [Html::class]];
|
||||
yield [__DIR__ . '/Source/ClassWithProperties.php', 1, [ClassThatExtendsHtml::class, Html::class]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\PropertyTypeResolver\Source;
|
||||
|
||||
class ClassThatExtendsHtml extends
|
||||
Html
|
||||
{
|
||||
|
||||
}
|
|
@ -8,4 +8,9 @@ final class MethodParamDocBlock
|
|||
* @var Html
|
||||
*/
|
||||
public $htmlProperty;
|
||||
|
||||
/**
|
||||
* @var ClassThatExtendsHtml
|
||||
*/
|
||||
public $anotherHtmlProperty;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\PropertyTypeResolver\Source;
|
||||
|
||||
final class Html
|
||||
class Html
|
||||
{
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\ProductRepository;
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\SomeProduct;
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\SomeRequest;
|
||||
|
||||
final class SomeController
|
||||
{
|
||||
|
@ -16,8 +18,7 @@ final class SomeController
|
|||
{
|
||||
$products = $this->productRepository->fetchAll();
|
||||
}
|
||||
|
||||
public function detail(Request $request, Product $product)
|
||||
public function detail(SomeRequest $request, SomeProduct $product)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source;
|
||||
|
||||
final class SomeProduct
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source;
|
||||
|
||||
final class SomeRequest
|
||||
{
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\ProductRepository;
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\SomeProduct;
|
||||
use Rector\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\Source\SomeRequest;
|
||||
|
||||
final class SomeController
|
||||
{
|
||||
|
@ -8,8 +10,7 @@ final class SomeController
|
|||
{
|
||||
$products = $productRepository->fetchAll();
|
||||
}
|
||||
|
||||
public function detail(Request $request, Product $product)
|
||||
public function detail(SomeRequest $request, SomeProduct $product)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user