Skip to content

Commit

Permalink
decouple ParamTypeInferer
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Aug 31, 2019
1 parent f9c44ec commit 36d4b65
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
use Rector\TypeDeclaration\Contract\TypeInferer\ParamTypeInfererInterface;
use Rector\TypeDeclaration\PhpDocParser\ParamPhpDocNodeFactory;
use Rector\TypeDeclaration\TypeInferer\ParamTypeInferer;

/**
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
Expand All @@ -26,27 +26,24 @@ final class AddArrayParamDocTypeRector extends AbstractRector
*/
private $docBlockManipulator;

/**
* @var ParamTypeInfererInterface[]
*/
private $paramTypeInferers = [];

/**
* @var ParamPhpDocNodeFactory
*/
private $paramPhpDocNodeFactory;

/**
* @param ParamTypeInfererInterface[] $paramTypeInferers
* @var ParamTypeInferer
*/
private $paramTypeInferer;

public function __construct(
DocBlockManipulator $docBlockManipulator,
array $paramTypeInferers,
ParamPhpDocNodeFactory $paramPhpDocNodeFactory
ParamPhpDocNodeFactory $paramPhpDocNodeFactory,
ParamTypeInferer $paramTypeInferer
) {
$this->docBlockManipulator = $docBlockManipulator;
$this->paramTypeInferers = $paramTypeInferers;
$this->paramPhpDocNodeFactory = $paramPhpDocNodeFactory;
$this->paramTypeInferer = $paramTypeInferer;
}

public function getDefinition(): RectorDefinition
Expand Down Expand Up @@ -114,15 +111,7 @@ public function refactor(Node $node): ?Node
return null;
}

$types = [];
foreach ($this->paramTypeInferers as $paramTypeInferer) {
$types = $paramTypeInferer->inferParam($param);
if ($types !== []) {
break;
}
}

// no types :/
$types = $this->paramTypeInferer->inferParam($param);
if ($types === []) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ final class AddArrayReturnDocTypeRector extends AbstractRector
*/
private $returnTypeInferer;

/**
* @param ReturnTypeInfererInterface[] $docBlockManipulator
*/
public function __construct(DocBlockManipulator $docBlockManipulator, ReturnTypeInferer $returnTypeInferer)
{
$this->docBlockManipulator = $docBlockManipulator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
use Rector\Php\TypeAnalyzer;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
use Rector\TypeDeclaration\ReturnTypeResolver\ReturnTypeResolver;
Expand All @@ -32,10 +33,19 @@ final class ReturnTypeDeclarationRector extends AbstractTypeDeclarationRector
*/
private $returnTypeInferer;

public function __construct(ReturnTypeResolver $returnTypeResolver, ReturnTypeInferer $returnTypeInferer)
{
/**
* @var TypeAnalyzer
*/
private $typeAnalyzer;

public function __construct(
ReturnTypeResolver $returnTypeResolver,
ReturnTypeInferer $returnTypeInferer,
TypeAnalyzer $typeAnalyzer
) {
$this->returnTypeResolver = $returnTypeResolver;
$this->returnTypeInferer = $returnTypeInferer;
$this->typeAnalyzer = $typeAnalyzer;
}

public function getDefinition(): RectorDefinition
Expand Down Expand Up @@ -128,11 +138,12 @@ public function refactor(Node $node): ?Node
}
}
} else {
$inferedTypes = $this->returnTypeInferer->inferFunctionLike($node);
dump($inferedTypes);

dump($returnTypeInfo->getTypeNode());
die;
if ($returnTypeInfo->getTypeNode() === null) {
$inferedTypes = $this->returnTypeInferer->inferFunctionLike($node);
if ($inferedTypes) {
$returnTypeInfo = new ReturnTypeInfo($inferedTypes, $this->typeAnalyzer, $inferedTypes);
}
}

$node->returnType = $returnTypeInfo->getTypeNode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\RectorDefinition;
use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\Exception\ConflictingPriorityException;
use Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

/**
Expand All @@ -24,18 +23,14 @@ final class PropertyTypeDeclarationRector extends AbstractRector
private $docBlockManipulator;

/**
* @var PropertyTypeInfererInterface[]
* @var PropertyTypeInferer
*/
private $propertyTypeInferers = [];
private $propertyTypeInferer;

/**
* @param PropertyTypeInfererInterface[] $propertyTypeInferers
*/
public function __construct(DocBlockManipulator $docBlockManipulator, array $propertyTypeInferers = [])
public function __construct(DocBlockManipulator $docBlockManipulator, PropertyTypeInferer $propertyTypeInferer)
{
$this->docBlockManipulator = $docBlockManipulator;

$this->sortAndSetPropertyTypeInferers($propertyTypeInferers);
$this->propertyTypeInferer = $propertyTypeInferer;
}

public function getDefinition(): RectorDefinition
Expand Down Expand Up @@ -64,12 +59,10 @@ public function refactor(Node $node): ?Node
return null;
}

foreach ($this->propertyTypeInferers as $propertyTypeInferer) {
$types = $propertyTypeInferer->inferProperty($node);
if ($types) {
$this->setNodeVarTypes($node, $types);
return $node;
}
$types = $this->propertyTypeInferer->inferProperty($node);
if ($types) {
$this->setNodeVarTypes($node, $types);
return $node;
}

return null;
Expand All @@ -84,28 +77,4 @@ private function setNodeVarTypes(Node $node, array $varTypes): Node

return $node;
}

/**
* @param PropertyTypeInfererInterface[] $propertyTypeInferers
*/
private function sortAndSetPropertyTypeInferers(array $propertyTypeInferers): void
{
foreach ($propertyTypeInferers as $propertyTypeInferer) {
$this->ensurePriorityIsUnique($propertyTypeInferer);
$this->propertyTypeInferers[$propertyTypeInferer->getPriority()] = $propertyTypeInferer;
}

krsort($this->propertyTypeInferers);
}

private function ensurePriorityIsUnique(PropertyTypeInfererInterface $propertyTypeInferer): void
{
if (! isset($this->propertyTypeInferers[$propertyTypeInferer->getPriority()])) {
return;
}

$alreadySetPropertyTypeInferer = $this->propertyTypeInferers[$propertyTypeInferer->getPriority()];

throw new ConflictingPriorityException($propertyTypeInferer, $alreadySetPropertyTypeInferer);
}
}
37 changes: 37 additions & 0 deletions packages/TypeDeclaration/src/TypeInferer/ParamTypeInferer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);

namespace Rector\TypeDeclaration\TypeInferer;

use PhpParser\Node\Param;
use Rector\TypeDeclaration\Contract\TypeInferer\ParamTypeInfererInterface;

final class ParamTypeInferer
{
/**
* @var ParamTypeInfererInterface[]
*/
private $paramTypeInferers = [];

/**
* @param ParamTypeInfererInterface[] $paramTypeInferers
*/
public function __construct(array $paramTypeInferers)
{
$this->paramTypeInferers = $paramTypeInferers;
}

/**
* @return string[]
*/
public function inferParam(Param $param): array
{
foreach ($this->paramTypeInferers as $paramTypeInferers) {
$types = $paramTypeInferers->inferParam($param);
if ($types !== []) {
return $types;
}
}

return [];
}
}
32 changes: 29 additions & 3 deletions packages/TypeDeclaration/src/TypeInferer/PropertyTypeInferer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use PhpParser\Node\Stmt\Property;
use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\Exception\ConflictingPriorityException;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

final class PropertyTypeInferer
{
Expand All @@ -17,21 +19,45 @@ final class PropertyTypeInferer
*/
public function __construct(array $propertyTypeInferers)
{
$this->propertyTypeInferers = $propertyTypeInferers;
$this->sortAndSetPropertyTypeInferers($propertyTypeInferers);
}

/**
* @property string[]
* @return string[]|IdentifierValueObject[]
*/
public function inferProperty(Property $property): array
{
foreach ($this->propertyTypeInferers as $propertyTypeInferers) {
$types = $propertyTypeInferers->inferFunctionLike($property);
$types = $propertyTypeInferers->inferProperty($property);
if ($types !== []) {
return $types;
}
}

return [];
}

/**
* @param PropertyTypeInfererInterface[] $propertyTypeInferers
*/
private function sortAndSetPropertyTypeInferers(array $propertyTypeInferers): void
{
foreach ($propertyTypeInferers as $propertyTypeInferer) {
$this->ensurePriorityIsUnique($propertyTypeInferer);
$this->propertyTypeInferers[$propertyTypeInferer->getPriority()] = $propertyTypeInferer;
}

krsort($this->propertyTypeInferers);
}

private function ensurePriorityIsUnique(PropertyTypeInfererInterface $propertyTypeInferer): void
{
if (! isset($this->propertyTypeInferers[$propertyTypeInferer->getPriority()])) {
return;
}

$alreadySetPropertyTypeInferer = $this->propertyTypeInferers[$propertyTypeInferer->getPriority()];

throw new ConflictingPriorityException($propertyTypeInferer, $alreadySetPropertyTypeInferer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\Stmt\Trait_;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\TypeDeclaration\Contract\TypeInferer\ReturnTypeInfererInterface;
use Rector\TypeDeclaration\TypeInferer\AbstractTypeInferer;
use Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

/**
* Infer return type from $this->variable → and get type $this->variable from @var annotation
Expand All @@ -33,7 +37,7 @@ public function __construct(PropertyTypeInferer $propertyTypeInferer)

/**
* @param ClassMethod|Closure|Function_ $functionLike
* @return string[]
* @return string[]|IdentifierValueObject[]
*/
public function inferFunctionLike(FunctionLike $functionLike): array
{
Expand All @@ -56,7 +60,7 @@ public function inferFunctionLike(FunctionLike $functionLike): array

private function matchSingleStmtReturnPropertyFetch(ClassMethod $classMethod): ?PropertyFetch
{
if (count($classMethod->stmts) !== 1) {
if (count((array) $classMethod->stmts) !== 1) {
return null;
}

Expand Down Expand Up @@ -84,18 +88,21 @@ private function matchSingleStmtReturnPropertyFetch(ClassMethod $classMethod): ?

private function getPropertyByPropertyFetch(PropertyFetch $propertyFetch): ?Property
{
/** @var Class_|Trait_|Interface_|null $class */
$class = $propertyFetch->getAttribute(AttributeKey::CLASS_NODE);
if ($class instanceof ClassLike) {
if ($class === null) {
return null;
}

/** @var string $propertyName */
$propertyName = $this->nameResolver->getName($propertyFetch->name);

foreach ($class->stmts as $stmt) {
if (!$stmt instanceof Property) {
if (! $stmt instanceof Property) {
continue;
}

if (!$this->nameResolver->isName($stmt, $propertyName)) {
if (! $this->nameResolver->isName($stmt, $propertyName)) {
continue;
}

Expand Down

0 comments on commit 36d4b65

Please sign in to comment.