decopule PropertyTypeResolver

This commit is contained in:
Tomas Votruba 2018-08-06 23:41:01 +02:00
parent a2eac6c719
commit 023270a1b3
2 changed files with 96 additions and 44 deletions

View File

@ -6,7 +6,6 @@ use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\TrinaryLogic;
@ -19,7 +18,6 @@ use Rector\BetterPhpDocParser\NodeAnalyzer\DocBlockAnalyzer;
use Rector\Node\Attribute;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
use Rector\Php\TypeAnalyzer;
final class NodeTypeResolver
{
@ -38,11 +36,6 @@ final class NodeTypeResolver
*/
private $docBlockAnalyzer;
/**
* @var TypeAnalyzer
*/
private $typeAnalyzer;
/**
* @var Broker
*/
@ -51,12 +44,10 @@ final class NodeTypeResolver
public function __construct(
ClassReflectionTypesResolver $classReflectionTypesResolver,
DocBlockAnalyzer $docBlockAnalyzer,
TypeAnalyzer $typeAnalyzer,
Broker $broker
) {
$this->classReflectionTypesResolver = $classReflectionTypesResolver;
$this->docBlockAnalyzer = $docBlockAnalyzer;
$this->typeAnalyzer = $typeAnalyzer;
$this->broker = $broker;
}
@ -91,23 +82,6 @@ final class NodeTypeResolver
return $this->resolveExprNode($node);
}
if ($node instanceof Property) {
// doc
$propertyTypes = $this->docBlockAnalyzer->getVarTypes($node);
if ($propertyTypes === []) {
return [];
}
$propertyTypes = $this->filterOutScalarTypes($propertyTypes);
foreach ($propertyTypes as $propertyType) {
$propertyClassReflection = $this->broker->getClass($propertyType);
$propertyTypes += $this->classReflectionTypesResolver->resolve($propertyClassReflection);
}
return $propertyTypes;
}
$nodeClass = get_class($node);
if (isset($this->perNodeTypeResolvers[$nodeClass])) {
return $this->perNodeTypeResolvers[$nodeClass]->resolve($node);
@ -203,22 +177,4 @@ final class NodeTypeResolver
return array_unique($variableTypes);
}
/**
* @param string[] $propertyTypes
* @return string[]
*/
private function filterOutScalarTypes(array $propertyTypes): array
{
foreach ($propertyTypes as $key => $type) {
if (! $this->typeAnalyzer->isPhpReservedType($type)) {
continue;
}
unset($propertyTypes[$key]);
}
if ($propertyTypes === ['null']) {
return [];
}
return $propertyTypes;
}
}

View File

@ -0,0 +1,96 @@
<?php declare(strict_types=1);
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Broker\Broker;
use Rector\BetterPhpDocParser\NodeAnalyzer\DocBlockAnalyzer;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
use Rector\Php\TypeAnalyzer;
final class PropertyTypeResolver implements PerNodeTypeResolverInterface
{
/**
* @var ClassReflectionTypesResolver
*/
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;
}
/**
* @return string[]
*/
public function getNodeClasses(): array
{
return [Property::class];
}
/**
* @param Property $propertyNode
* @return string[]
*/
public function resolve(Node $propertyNode): array
{
// doc
$propertyTypes = $this->docBlockAnalyzer->getVarTypes($propertyNode);
if ($propertyTypes === []) {
return [];
}
$propertyTypes = $this->filterOutScalarTypes($propertyTypes);
foreach ($propertyTypes as $propertyType) {
$propertyClassReflection = $this->broker->getClass($propertyType);
$propertyTypes += $this->classReflectionTypesResolver->resolve($propertyClassReflection);
}
return $propertyTypes;
}
/**
* @param string[] $propertyTypes
* @return string[]
*/
private function filterOutScalarTypes(array $propertyTypes): array
{
foreach ($propertyTypes as $key => $type) {
if (! $this->typeAnalyzer->isPhpReservedType($type)) {
continue;
}
unset($propertyTypes[$key]);
}
if ($propertyTypes === ['null']) {
return [];
}
return $propertyTypes;
}
}