slowly remove CallerTypeNode resolving, use directly TypeResolver

This commit is contained in:
TomasVotruba 2018-01-07 15:29:30 +01:00
parent 85a0972775
commit 2e2c77baa0
5 changed files with 60 additions and 27 deletions

View File

@ -8,6 +8,7 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\NodeVisitorAbstract;
use Rector\Node\Attribute;
use Rector\NodeTypeResolver\NodeCallerTypeResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;
/**
* This will tell the type of Node, which is calling this method
@ -23,21 +24,40 @@ final class CallerTypeNodeVisitor extends NodeVisitorAbstract
* @var NodeCallerTypeResolver
*/
private $nodeCallerTypeResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(NodeCallerTypeResolver $nodeCallerTypeResolver)
public function __construct(NodeCallerTypeResolver $nodeCallerTypeResolver, NodeTypeResolver $nodeTypeResolver)
{
$this->nodeCallerTypeResolver = $nodeCallerTypeResolver;
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function enterNode(Node $node): ?Node
{
if (! $node instanceof StaticCall && ! $node instanceof MethodCall) {
if ($node instanceof StaticCall) {
$types = $this->nodeTypeResolver->resolve($node->class);
$node->setAttribute(Attribute::CALLER_TYPES, $types);
return $node;
}
$types = $this->nodeCallerTypeResolver->resolve($node);
if ($types) {
if ($node instanceof MethodCall) {
$nodeTypeResolverTypes = $this->nodeTypeResolver->resolve($node->var);
$types = $this->nodeCallerTypeResolver->resolve($node);
if ($nodeTypeResolverTypes !== $types) {
dump($nodeTypeResolverTypes);
dump($types);
throw new \Exception('aa');
die;
}
$node->setAttribute(Attribute::CALLER_TYPES, $types);
return $node;
}
return null;

View File

@ -63,6 +63,8 @@ final class MethodCallCallerTypeResolver implements PerNodeCallerTypeResolverInt
$returnTypes = $this->methodReflector->resolveReturnTypesForTypesAndMethod($parentReturnTypes, $methodName);
dump($returnTypes);
if ($returnTypes) {
return $returnTypes;
}

View File

@ -2,6 +2,7 @@
namespace Rector\NodeTypeResolver\PerNodeTypeResolver;
use Nette\Reflection\Method;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
@ -9,14 +10,16 @@ use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use Rector\BetterReflection\Reflector\MethodReflector;
use Rector\Node\Attribute;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\TypeContext;
/**
* This resolves return type of method call,
* not types of its elements.
*/
final class MethodCallTypeResolver implements PerNodeTypeResolverInterface
final class MethodCallTypeResolver implements PerNodeTypeResolverInterface, NodeTypeResolverAwareInterface
{
/**
* @var TypeContext
@ -28,6 +31,11 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface
*/
private $methodReflector;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(TypeContext $typeContext, MethodReflector $methodReflector)
{
$this->typeContext = $typeContext;
@ -53,32 +61,34 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface
/** @var Variable|mixed $variableNode */
$variableNode = $methodCallNode->var;
if (! $variableNode instanceof Variable) {
if (! $variableNode instanceof Variable && ! $variableNode instanceof MethodCall) {
return [];
}
$variableName = (string) $variableNode->name;
$parentCallerTypes = [];
$methodCallVariableTypes = $this->typeContext->getTypesForVariable($variableName);
// chain method calls: $this->someCall()->anotherCall()
if ($methodCallNode->var instanceof MethodCall) {
$parentCallerTypes = $this->nodeTypeResolver->resolve($methodCallNode->var);
}
$methodCallName = $this->resolveMethodCallName($methodCallNode);
// $this->someCall()
if ($methodCallNode->var instanceof Variable) {
$parentCallerTypes = $this->nodeTypeResolver->resolve($methodCallNode->var);
}
if (! $methodCallVariableTypes || ! $methodCallName) {
$methodCallName = $methodCallNode->name->toString();
if (! $parentCallerTypes || ! $methodCallName) {
return [];
}
$methodCallVariableType = array_shift($methodCallVariableTypes);
return $this->resolveMethodReflectionReturnTypes($methodCallNode, $methodCallVariableType, $methodCallName);
return $this->resolveMethodReflectionReturnTypes($methodCallNode, $parentCallerTypes, $methodCallName);
}
private function resolveMethodCallName(MethodCall $methodCallNode): ?string
public function setNodeTypeResolver(NodeTypeResolver $nodeTypeResolver): void
{
if ($methodCallNode->name instanceof Identifier) {
return $methodCallNode->name->toString();
}
return null;
$this->nodeTypeResolver= $nodeTypeResolver;
}
private function getVariableToAssignTo(MethodCall $methodCallNode): ?string
@ -103,12 +113,12 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface
*/
private function resolveMethodReflectionReturnTypes(
MethodCall $methodCallNode,
string $class,
array $methodCallVariableTypes,
string $method
): array {
$variableTypes = $this->methodReflector->getMethodReturnTypes($class, $method);
if (! $variableTypes) {
return [];
$methodReturnTypes = $this->methodReflector->resolveReturnTypesForTypesAndMethod($methodCallVariableTypes, $method);
if ($methodReturnTypes) {
return $methodReturnTypes;
}
$variableName = $this->getVariableToAssignTo($methodCallNode);
@ -116,8 +126,8 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface
return [];
}
$this->typeContext->addVariableWithTypes($variableName, $variableTypes);
$this->typeContext->addVariableWithTypes($variableName, $methodReturnTypes);
return $variableTypes;
return $methodReturnTypes;
}
}

View File

@ -21,6 +21,7 @@ use Rector\Rector\AbstractRector;
*
* To:
* $builder->parameters['argument'];
* $builder->parameters['argument'];
*/
final class ExpandFunctionToParametersArrayRector extends AbstractRector
{

View File

@ -21,10 +21,10 @@ final class ArgumentReplacerRectorTest extends AbstractConfigurableRectorTestCas
public function provideWrongToFixedFiles(): array
{
return [
[__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'],
[__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc'],
// [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'],
// [__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc'],
[__DIR__ . '/Wrong/wrong3.php.inc', __DIR__ . '/Correct/correct3.php.inc'],
[__DIR__ . '/Wrong/wrong4.php.inc', __DIR__ . '/Correct/correct4.php.inc'],
// [__DIR__ . '/Wrong/wrong4.php.inc', __DIR__ . '/Correct/correct4.php.inc'],
];
}