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
1 change: 1 addition & 0 deletions ecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ services:
- 'Rector\DependencyInjection\Loader\*'
- 'Symplify\PackageBuilder\*'
- 'Symfony\Component\Console\Input\*Input'
- '*ValueObject'

Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
extra_skipped_classes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
use Rector\NodeTypeResolver\Php\VarTypeInfo;
use Rector\Php\TypeAnalyzer;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

final class DocBlockManipulator
{
Expand Down Expand Up @@ -256,7 +257,10 @@ public function getTagsByName(Node $node, string $name): array
return $phpDocInfo->getTagsByName($name);
}

public function changeVarTag(Node $node, string $type): void
/**
* @param string|string[]|IdentifierValueObject|IdentifierValueObject[] $type
*/
public function changeVarTag(Node $node, $type): void
{
$this->removeTagFromNode($node, 'var', true);
$this->addTypeSpecificTag($node, 'var', $type);
Expand Down Expand Up @@ -547,11 +551,20 @@ public function createPhpDocInfoFromNode(Node $node): PhpDocInfo
/**
* All class-type tags are FQN by default to keep default convention through the code.
* Some people prefer FQN, some short. FQN can be shorten with \Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector later, while short prolonged not
* @param string|string[]|IdentifierValueObject|IdentifierValueObject[] $type
*/
private function addTypeSpecificTag(Node $node, string $name, string $type): void
private function addTypeSpecificTag(Node $node, string $name, $type): void
{
// preffix possible class name
$type = $this->preslashFullyQualifiedNames($type);
if (! is_array($type)) {
$type = [$type];
}

foreach ($type as $key => $singleType) {
// prefix possible class name
$type[$key] = $this->preslashFullyQualifiedNames($singleType);
}

$type = implode('|', $type);

// there might be no phpdoc at all
if ($node->getDocComment() !== null) {
Expand Down Expand Up @@ -681,8 +694,19 @@ private function processFqnNameImport(
return $attributeAwareNode;
}

private function preslashFullyQualifiedNames(string $type): string
/**
* @param string|IdentifierValueObject $type
*/
private function preslashFullyQualifiedNames($type): string
{
if ($type instanceof IdentifierValueObject) {
if ($type->isAlias()) {
return $type->getName();
}

$type = $type->getName();
}

$joinChar = '|'; // default
if (Strings::contains($type, '|')) { // intersection
$types = explode('|', $type);
Expand Down
2 changes: 1 addition & 1 deletion packages/TypeDeclaration/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ services:

Rector\TypeDeclaration\:
resource: '../src/'
exclude: '../src/{Rector/**/*Rector.php,Exception}'
exclude: '../src/{Rector/**/*Rector.php,Exception,ValueObject/*}'
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Rector\TypeDeclaration\Contract;

use PhpParser\Node\Stmt\Property;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

interface PropertyTypeInfererInterface
{
/**
* @return string[]
* @return string[]|IdentifierValueObject[]
*/
public function inferProperty(Property $property): array;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Rector\TypeDeclaration\PropertyTypeInferer;

use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
Expand All @@ -12,11 +13,12 @@
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\TypeDeclaration\Contract\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

final class ConstructorPropertyTypeInferer extends AbstractPropertyTypeInferer implements PropertyTypeInfererInterface
{
/**
* @return string[]
* @return string[]|IdentifierValueObject[]
*/
public function inferProperty(Node\Stmt\Property $property): array
{
Expand Down Expand Up @@ -174,7 +176,10 @@ private function isParamNullable(Node\Param $param): bool
return false;
}

private function resolveParamTypeToString(Node\Param $param): ?string
/**
* @return IdentifierValueObject|string|null
*/
private function resolveParamTypeToString(Node\Param $param)
{
if ($param->type === null) {
return null;
Expand All @@ -184,6 +189,19 @@ private function resolveParamTypeToString(Node\Param $param): ?string
return $this->nameResolver->resolve($param->type->type);
}

// special case for alias
if ($param->type instanceof Node\Name\FullyQualified) {
$fullyQualifiedName = $param->type->toString();
$originalName = $param->type->getAttribute('originalName');

if ($fullyQualifiedName && $originalName instanceof Node\Name) {
// if the FQN has different ending than the original, it was aliased and we need to return the alias
if (! Strings::endsWith($fullyQualifiedName, '\\' . $originalName->toString())) {
return new IdentifierValueObject($originalName->toString(), true);
}
}
}

return $this->nameResolver->resolve($param->type);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ private function resolveRelationType(Property $property, string $doctrineRelatio
if ($relationTag->value instanceof GenericTagValueNode) {
$resolveTargetType = $this->resolveTargetEntity($relationTag->value);
if ($resolveTargetType) {
if (Strings::contains($resolveTargetType, '\\')) {
return $resolveTargetType;
}

// is FQN?
if (! class_exists($resolveTargetType)) {
return $this->namespaceAnalyzer->resolveTypeToFullyQualified($resolveTargetType, $property);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rector\RectorDefinition\RectorDefinition;
use Rector\TypeDeclaration\Contract\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\Exception\ConflictingPriorityException;
use Rector\TypeDeclaration\ValueObject\IdentifierValueObject;

final class PropertyTypeDeclarationRector extends AbstractRector
{
Expand Down Expand Up @@ -72,13 +73,11 @@ public function refactor(Node $node): ?Node
}

/**
* @param string[] $varTypes
* @param string[]|IdentifierValueObject[] $varTypes
*/
private function setNodeVarTypes(Node $node, array $varTypes): Node
{
$typesAsString = implode('|', $varTypes);

$this->docBlockManipulator->changeVarTag($node, $typesAsString);
$this->docBlockManipulator->changeVarTag($node, $varTypes);

return $node;
}
Expand Down
32 changes: 32 additions & 0 deletions packages/TypeDeclaration/src/ValueObject/IdentifierValueObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);

namespace Rector\TypeDeclaration\ValueObject;

final class IdentifierValueObject
{
/**
* @var string
*/
private $name;

/**
* @var bool
*/
private $isAlias = false;

public function __construct(string $name, bool $isAlias)
{
$this->name = $name;
$this->isAlias = $isAlias;
}

public function getName(): string
{
return $this->name;
}

public function isAlias(): bool
{
return $this->isAlias;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

namespace Rector\TypeDeclaration\Tests\Rector\FunctionLike\PropertyTypeDeclarationRector\Fixture;

class Param {}

use Rector\TypeDeclaration\Tests\Rector\FunctionLike\PropertyTypeDeclarationRector\Fixture\Param as Aliased;
use Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRector\Source\ObjectToBeAliased as Aliased;

class ConstructorParamWithAliasedParam
{
Expand All @@ -22,9 +20,7 @@ class ConstructorParamWithAliasedParam

namespace Rector\TypeDeclaration\Tests\Rector\FunctionLike\PropertyTypeDeclarationRector\Fixture;

class Param {}

use Rector\TypeDeclaration\Tests\Rector\FunctionLike\PropertyTypeDeclarationRector\Fixture\Param as Aliased;
use Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRector\Source\ObjectToBeAliased as Aliased;

class ConstructorParamWithAliasedParam
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types=1);

namespace Rector\TypeDeclaration\Tests\Rector\Property\PropertyTypeDeclarationRector\Source;

final class ObjectToBeAliased
{

}