[NodeTypeResolver] refactor to callabacks to decrease complexity

This commit is contained in:
TomasVotruba 2017-08-21 11:35:57 +02:00
parent b6345de749
commit d013fe2534
3 changed files with 51 additions and 27 deletions

View File

@ -28,9 +28,24 @@ final class ClassLikeTypeResolver extends NodeVisitorAbstract
*/
private $typeContext;
/**
* @var callable[]
*/
private $perNodeResolvers = [];
public function __construct(TypeContext $typeContext)
{
$this->typeContext = $typeContext;
$this->perNodeResolvers[Variable::class] = function (Variable $variableNode): void {
$this->processVariableNode($variableNode);
};
$this->perNodeResolvers[Assign::class] = function (Assign $assignNode): void {
$this->processAssignNode($assignNode);
};
$this->perNodeResolvers[PropertyFetch::class] = function (PropertyFetch $propertyFetchNode): void {
$this->processPropertyFetch($propertyFetchNode);
};
}
/**
@ -55,16 +70,10 @@ final class ClassLikeTypeResolver extends NodeVisitorAbstract
return;
}
if ($node instanceof Variable) {
$this->processVariableNode($node);
}
$nodeClass = get_class($node);
if ($node instanceof Assign) {
$this->processAssignNode($node);
}
if ($node instanceof PropertyFetch) {
$this->processPropertyFetch($node);
if (isset($this->perNodeResolvers[$nodeClass])) {
$this->perNodeResolvers[$nodeClass]($node);
}
}

View File

@ -57,7 +57,7 @@ final class TypeContext
$this->classLikeNode = $classLikeNode;
if ($classLikeNode instanceof Class_) {
$this->classProperties = $this-> constructorPropertyTypesExtractor->extractFromClassNode($classLikeNode);
$this->classProperties = $this->constructorPropertyTypesExtractor->extractFromClassNode($classLikeNode);
}
}

View File

@ -7,6 +7,7 @@ use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use ReflectionClass;
final class ConstructorPropertyTypesExtractor
{
@ -20,29 +21,15 @@ final class ConstructorPropertyTypesExtractor
return [];
}
$propertiesWithTypes = [];
foreach ($classNode->stmts as $inClassNode) {
if (! $this->isContructorMethodNode($inClassNode)) {
continue;
}
foreach ($inClassNode->stmts as $inConstructorNode) {
if (! $this->isAssignThisNode($inConstructorNode)) {
continue;
}
/** @var PropertyFetch $propertyFetchNode */
$propertyFetchNode = $inConstructorNode->expr->var;
$propertyName = (string) $propertyFetchNode->name;
$propertyType = $constructorParametersWithTypes[$propertyName] ?? null;
if ($propertyName && $propertyType) {
$propertiesWithTypes[$propertyName] = $propertyType;
}
}
return $this->extractPropertiesFromConstructorMethodNode($inClassNode, $constructorParametersWithTypes);
}
return $propertiesWithTypes;
return [];
}
/**
@ -55,7 +42,7 @@ final class ConstructorPropertyTypesExtractor
return [];
}
$constructorMethod = (new \ReflectionClass($className))->getConstructor();
$constructorMethod = (new ReflectionClass($className))->getConstructor();
$parametersWithTypes = [];
if ($constructorMethod) {
@ -91,4 +78,32 @@ final class ConstructorPropertyTypesExtractor
return $node->expr->var->var->name === 'this';
}
/**
* @param string[] $constructorParametersWithTypes
* @return string[]
*/
private function extractPropertiesFromConstructorMethodNode(
ClassMethod $classMethodNode,
array $constructorParametersWithTypes
): array {
$propertiesWithTypes = [];
foreach ($classMethodNode->stmts as $inConstructorNode) {
if (! $this->isAssignThisNode($inConstructorNode)) {
continue;
}
/** @var PropertyFetch $propertyFetchNode */
$propertyFetchNode = $inConstructorNode->expr->var;
$propertyName = (string) $propertyFetchNode->name;
$propertyType = $constructorParametersWithTypes[$propertyName] ?? null;
if ($propertyName && $propertyType) {
$propertiesWithTypes[$propertyName] = $propertyType;
}
}
return $propertiesWithTypes;
}
}