Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/NodeTypeResolver/src/Php/AbstractTypeInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ public function getDocTypes(): array
{
$allTypes = array_merge($this->types, $this->removedTypes);

if ($this->isNullable) {
$allTypes[] = 'null';
}

return array_filter(array_unique($allTypes));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ class Command
*/
protected static $defaultName;
/**
* @var \Symfony\Component\Console\Application
* @var \Symfony\Component\Console\Application|null
*/
private $application;
/**
Expand Down Expand Up @@ -642,7 +642,7 @@ class Command
*/
private $usages = array();
/**
* @var \Symfony\Component\Console\Helper\HelperSet
* @var \Symfony\Component\Console\Helper\HelperSet|null
*/
private $helperSet;
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@
namespace Rector\TypeDeclaration\PropertyTypeInferer;

use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Return_;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\Printer\BetterStandardPrinter;
use Rector\TypeDeclaration\Contract\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\ReturnTypeResolver\ReturnTypeResolver;

final class GetterOrSetterPropertyTypeInferer extends AbstractPropertyTypeInferer implements PropertyTypeInfererInterface
{
/**
* @var BetterStandardPrinter
* @var ReturnTypeResolver
*/
private $betterStandardPrinter;
private $returnTypeResolver;

public function __construct(BetterStandardPrinter $betterStandardPrinter)
public function __construct(ReturnTypeResolver $returnTypeResolver)
{
$this->betterStandardPrinter = $betterStandardPrinter;
$this->returnTypeResolver = $returnTypeResolver;
}

/**
Expand All @@ -40,16 +38,11 @@ public function inferProperty(Property $property): array
if (! $this->hasClassMethodOnlyStatementReturnOfPropertyFetch($classMethod, $propertyName)) {
continue;
}

$returnTypes = $this->resolveClassMethodReturnTypes($classMethod);
if ($returnTypes !== []) {
return $returnTypes;
}

throw new ShouldNotHappenException(sprintf(
'"%s" for "%s" type',
__METHOD__,
$this->betterStandardPrinter->print($classMethod->returnType)
));
}

return [];
Expand Down Expand Up @@ -88,28 +81,11 @@ private function hasClassMethodOnlyStatementReturnOfPropertyFetch(
*/
private function resolveClassMethodReturnTypes(ClassMethod $classMethod): array
{
// @todo resolve from doc?
if (! $classMethod->returnType) {
$returnType = $this->returnTypeResolver->resolveFunctionLikeReturnType($classMethod);
if ($returnType === null) {
return [];
}

if ($classMethod->returnType instanceof NullableType) {
$type = $classMethod->returnType->type;
} else {
$type = $classMethod->returnType;
}

$result = $this->nameResolver->resolve($type);
if ($result !== null) {
$types = [$result];

if ($classMethod->returnType instanceof NullableType) {
$types[] = 'null';
}

return $types;
}

return [];
return $returnType->getDocTypes();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
/**
* @var string
*/
protected const HAS_NEW_INHERITED_TYPE = 'has_new_inherited_return_type';
public const HAS_NEW_INHERITED_TYPE = 'has_new_inherited_return_type';

/**
* @var DocBlockManipulator
Expand All @@ -49,11 +49,14 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
*/
protected $functionLikeManipulator;

public function __construct(
/**
* @required
*/
public function autowireAbstractTypeDeclarationRector(
DocBlockManipulator $docBlockManipulator,
ParsedNodesByType $parsedNodesByType,
FunctionLikeManipulator $functionLikeManipulator
) {
): void {
$this->docBlockManipulator = $docBlockManipulator;
$this->parsedNodesByType = $parsedNodesByType;
$this->functionLikeManipulator = $functionLikeManipulator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Rector\TypeDeclaration\Rector\FunctionLike;

use PhpParser\Node;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
Expand All @@ -13,6 +12,7 @@
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
use Rector\TypeDeclaration\ReturnTypeResolver\ReturnTypeResolver;

final class ReturnTypeDeclarationRector extends AbstractTypeDeclarationRector
{
Expand All @@ -21,6 +21,16 @@ final class ReturnTypeDeclarationRector extends AbstractTypeDeclarationRector
*/
private const EXCLUDED_METHOD_NAMES = ['__construct', '__destruct', '__clone'];

/**
* @var ReturnTypeResolver
*/
private $returnTypeResolver;

public function __construct(ReturnTypeResolver $returnTypeResolver)
{
$this->returnTypeResolver = $returnTypeResolver;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
Expand Down Expand Up @@ -82,7 +92,7 @@ public function refactor(Node $node): ?Node
}
}

$returnTypeInfo = $this->resolveReturnType($node);
$returnTypeInfo = $this->returnTypeResolver->resolveFunctionLikeReturnType($node);
if ($returnTypeInfo === null) {
return null;
}
Expand Down Expand Up @@ -125,26 +135,6 @@ public function refactor(Node $node): ?Node
return $node;
}

/**
* @param ClassMethod|Function_ $functionLike
*/
private function resolveReturnType(FunctionLike $functionLike): ?ReturnTypeInfo
{
$docReturnTypeInfo = $this->docBlockManipulator->getReturnTypeInfo($functionLike);
$codeReturnTypeInfo = $this->functionLikeManipulator->resolveStaticReturnTypeInfo($functionLike);

// code has priority over docblock
if ($docReturnTypeInfo === null) {
return $codeReturnTypeInfo;
}

if ($codeReturnTypeInfo && $codeReturnTypeInfo->getTypeNode()) {
return $codeReturnTypeInfo;
}

return $docReturnTypeInfo;
}

/**
* Add typehint to all children
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);

namespace Rector\TypeDeclaration\ReturnTypeResolver;

use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\PhpParser\Node\Manipulator\FunctionLikeManipulator;

final class ReturnTypeResolver
{
/**
* @var DocBlockManipulator
*/
private $docBlockManipulator;

/**
* @var FunctionLikeManipulator
*/
private $functionLikeManipulator;

public function __construct(
DocBlockManipulator $docBlockManipulator,
FunctionLikeManipulator $functionLikeManipulator
) {
$this->docBlockManipulator = $docBlockManipulator;
$this->functionLikeManipulator = $functionLikeManipulator;
}

/**
* @param ClassMethod|Function_ $functionLike
*/
public function resolveFunctionLikeReturnType(FunctionLike $functionLike): ?ReturnTypeInfo
{
$docReturnTypeInfo = $this->docBlockManipulator->getReturnTypeInfo($functionLike);
$codeReturnTypeInfo = $this->functionLikeManipulator->resolveStaticReturnTypeInfo($functionLike);

// code has priority over docblock
if ($docReturnTypeInfo === null) {
return $codeReturnTypeInfo;
}

if ($codeReturnTypeInfo && $codeReturnTypeInfo->getTypeNode()) {
return $codeReturnTypeInfo;
}

return $docReturnTypeInfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixture\Iterable;

class A {
class AnIterableClass {
/** @return iterable */
public function getIterable($value) {
return $value;
}
}
class B extends A {
class BuildOnThePreviousClass extends AnIterableClass {
/** @return array */
public function getIterable($value) {
return $value;
Expand All @@ -21,13 +21,13 @@ class B extends A {

namespace Rector\TypeDeclaration\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixture\Iterable;

class A {
class AnIterableClass {
/** @return iterable */
public function getIterable($value): iterable {
return $value;
}
}
class B extends A {
class BuildOnThePreviousClass extends AnIterableClass {
/** @return array */
public function getIterable($value): array {
return $value;
Expand Down
Loading