From e80f408a754e2d7fd66891a06a4e58fa271af343 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 25 Oct 2017 11:18:48 +0200 Subject: [PATCH] prepare support for multi-types [ref #97] --- .../NodeTypeResolver/src/NodeTypeResolver.php | 2 +- .../PerNodeTypeResolver/AssignTypeResolver.php | 12 +++++++++--- .../MethodCallTypeResolver.php | 8 +++++--- .../src/PerNodeTypeResolver/NameTypeResolver.php | 15 ++++++++------- .../PerNodeTypeResolver/PropertyTypeResolver.php | 2 +- packages/NodeTypeResolver/src/TypeContext.php | 14 ++++++++++---- .../ClassLikeTypeResolver/Test.php | 2 +- 7 files changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/NodeTypeResolver/src/NodeTypeResolver.php b/packages/NodeTypeResolver/src/NodeTypeResolver.php index fb9e40b39b4..40764806451 100644 --- a/packages/NodeTypeResolver/src/NodeTypeResolver.php +++ b/packages/NodeTypeResolver/src/NodeTypeResolver.php @@ -36,6 +36,6 @@ final class NodeTypeResolver return $perNodeTypeResolver->resolve($node); } - return null; + return []; } } diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/AssignTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/AssignTypeResolver.php index 1be9f5ff81f..06b18b94bf7 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/AssignTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/AssignTypeResolver.php @@ -62,7 +62,10 @@ final class AssignTypeResolver implements PerNodeTypeResolverInterface, NodeType $this->nodeTypeResolver = $nodeTypeResolver; } - private function processAssignVariableNode(Assign $assignNode): ?string + /** + * @return string[] + */ + private function processAssignVariableNode(Assign $assignNode): array { if ($assignNode->var->name instanceof Variable) { $name = $assignNode->var->name->name; @@ -75,7 +78,10 @@ final class AssignTypeResolver implements PerNodeTypeResolverInterface, NodeType return $this->typeContext->getTypesForVariable($name); } - private function resolveTypeForRightSide(Assign $assignNode): ?string + /** + * @return string[] + */ + private function resolveTypeForRightSide(Assign $assignNode): array { // $var = $anotherVar; if ($assignNode->expr instanceof Variable) { @@ -92,6 +98,6 @@ final class AssignTypeResolver implements PerNodeTypeResolverInterface, NodeType return $this->nodeTypeResolver->resolve($assignNode->expr); } - return null; + return []; } } diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/MethodCallTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/MethodCallTypeResolver.php index 402f1cac516..82005489e44 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/MethodCallTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/MethodCallTypeResolver.php @@ -52,15 +52,17 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface $variableName = $variableNode->name; - $methodCallVariableType = $this->typeContext->getTypesForVariable($variableName); + $methodCallVariableTypes = $this->typeContext->getTypesForVariable($variableName); $methodCallName = $this->resolveMethodCallName($methodCallNode); // 2. get method() return type - if (! $methodCallVariableType || ! $methodCallName) { + if (! $methodCallVariableTypes || ! $methodCallName) { return null; } + $methodCallVariableType = array_pop($methodCallVariableTypes); + $variableType = $this->methodReflector->getMethodReturnType($methodCallVariableType, $methodCallName); if ($variableType) { $variableName = $this->getVariableToAssignTo($methodCallNode); @@ -68,7 +70,7 @@ final class MethodCallTypeResolver implements PerNodeTypeResolverInterface return null; } - $this->typeContext->addVariableWithType($variableName, $variableType); + $this->typeContext->addVariableWithType($variableName, [$variableType]); } return [$variableType]; diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php index 5cd1a303ff0..3f42411f1c8 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php @@ -31,22 +31,23 @@ final class NameTypeResolver implements PerNodeTypeResolverInterface */ public function resolve(Node $nameNode): array { - $types = []; - /** @var Name|null $fqnName */ $fqnName = $nameNode->getAttribute(Attribute::RESOLVED_NAME); - if ($fqnName instanceof Name) { + $types = []; + if ($fqnName) { $types[] = $fullyQualifiedName = $fqnName->toString(); + } - $classLikeReflection = $this->smartClassReflector->reflect($fullyQualifiedName); + if ($fqnName instanceof Name) { + if ($fullyQualifiedName) { + $classLikeReflection = $this->smartClassReflector->reflect($fullyQualifiedName); + } $types = array_merge($types, array_keys($classLikeReflection->getInterfaces())); $types = array_merge($types, $classLikeReflection->getParentClassNames()); - - return $types; } - return $nameNode->toString(); + return $types; } } diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/PropertyTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/PropertyTypeResolver.php index f7147b5fde6..196c64e19bc 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/PropertyTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/PropertyTypeResolver.php @@ -57,7 +57,7 @@ final class PropertyTypeResolver implements PerNodeTypeResolverInterface $propertyType = $this->namespaceAnalyzer->resolveTypeToFullyQualified($propertyType, $propertyNode); - $this->typeContext->addPropertyType($propertyName, $propertyType); + $this->typeContext->addPropertyTypes($propertyName, $propertyType); return [$propertyType]; } diff --git a/packages/NodeTypeResolver/src/TypeContext.php b/packages/NodeTypeResolver/src/TypeContext.php index de7cdbb7d6a..758f5fdb5a0 100644 --- a/packages/NodeTypeResolver/src/TypeContext.php +++ b/packages/NodeTypeResolver/src/TypeContext.php @@ -66,9 +66,12 @@ final class TypeContext $this->classLikeNode = null; } - public function addVariableWithType(string $variableName, string $variableType): void + /** + * @param string[] $variableTypes + */ + public function addVariableWithType(string $variableName, array $variableTypes): void { - $this->variableTypes[$variableName] = $variableType; + $this->variableTypes[$variableName] = $variableTypes; } public function enterClassLike(ClassLike $classLikeNode): void @@ -117,9 +120,12 @@ final class TypeContext $this->addVariableWithType($newVariable, $type); } - public function addPropertyType(string $propertyName, string $propertyType): void + /** + * @param string[] $propertyTypes + */ + public function addPropertyTypes(string $propertyName, array $propertyTypes): void { - $this->propertyTypes[$propertyName] = $propertyType; + $this->propertyTypes[$propertyName] = $propertyTypes; } /** diff --git a/packages/NodeTypeResolver/tests/PerNodeTypeResolver/ClassLikeTypeResolver/Test.php b/packages/NodeTypeResolver/tests/PerNodeTypeResolver/ClassLikeTypeResolver/Test.php index ea7948ea0f2..fa405a49903 100644 --- a/packages/NodeTypeResolver/tests/PerNodeTypeResolver/ClassLikeTypeResolver/Test.php +++ b/packages/NodeTypeResolver/tests/PerNodeTypeResolver/ClassLikeTypeResolver/Test.php @@ -14,7 +14,7 @@ final class Test extends AbstractNodeTypeResolverTest $variableNodes = $this->getNodesForFileOfType($file, Variable::class); $this->assertSame( - 'SomeNamespace\SomeClass_SomeNamespace\SomeInterface', + ['SomeNamespace\SomeClass', 'SomeNamespace\SomeInterface'], $variableNodes[0]->getAttribute(Attribute::TYPES) ); }