fix alias object conflict with existing type

This commit is contained in:
TomasVotruba 2019-12-26 12:09:09 +01:00
parent e0bfbda7ca
commit 4407860e79
5 changed files with 65 additions and 7 deletions

View File

@ -39,6 +39,7 @@ use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Exception\MissingTagException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\StaticTypeMapper;
use Rector\PHPStan\Type\AliasedObjectType;
use Rector\PHPStan\Type\ShortenedObjectType;
/**
@ -311,7 +312,9 @@ final class DocBlockManipulator
return new MixedType();
}
return $this->createPhpDocInfoFromNode($node)->getVarType();
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
return $phpDocInfo->getVarType();
}
public function removeTagByName(PhpDocInfo $phpDocInfo, string $tagName): void
@ -539,6 +542,19 @@ final class DocBlockManipulator
*/
private function areTypesEquals(Type $firstType, Type $secondType): bool
{
// aliases and types
if ($firstType instanceof AliasedObjectType && $secondType instanceof ObjectType) {
if ($firstType->getFullyQualifiedClass() === $secondType->getClassName()) {
return true;
}
}
if ($secondType instanceof AliasedObjectType && $firstType instanceof ObjectType) {
if ($secondType->getFullyQualifiedClass() === $firstType->getClassName()) {
return true;
}
}
$firstTypeHash = $this->staticTypeMapper->createTypeHash($firstType);
$secondTypeHash = $this->staticTypeMapper->createTypeHash($secondType);

View File

@ -8,4 +8,19 @@ use PHPStan\Type\ObjectType;
final class AliasedObjectType extends ObjectType
{
/**
* @var string
*/
private $fullyQualifiedClass;
public function __construct(string $alias, string $fullyQualifiedClass)
{
parent::__construct($alias);
$this->fullyQualifiedClass = $fullyQualifiedClass;
}
public function getFullyQualifiedClass(): string
{
return $this->fullyQualifiedClass;
}
}

View File

@ -30,6 +30,7 @@ final class ObjectTypeSpecifier
}
$aliasedObjectType = $this->matchAliasedObjectType($node, $objectType);
if ($aliasedObjectType !== null) {
return $aliasedObjectType;
}
@ -68,11 +69,18 @@ final class ObjectTypeSpecifier
}
$useName = $useUse->name->toString();
if ($useName !== $objectType->getClassName()) {
continue;
$alias = $useUse->alias->toString();
$fullyQualifiedName = $useUse->name->toString();
// A. is alias in use statement matching this class alias
if ($useUse->alias->toString() === $objectType->getClassName()) {
return new AliasedObjectType($alias, $fullyQualifiedName);
}
return new AliasedObjectType($useUse->alias->toString());
// B. is aliased classes matching the class name
if ($useName === $objectType->getClassName()) {
return new AliasedObjectType($alias, $fullyQualifiedName);
}
}
}

View File

@ -143,7 +143,7 @@ final class ConstructorPropertyTypeInferer extends AbstractTypeInferer implement
// special case for alias
if ($param->type instanceof FullyQualified) {
$type = $this->resolveFullyQualifiedOrAlaisedObjectType($param);
$type = $this->resolveFullyQualifiedOrAliasedObjectType($param);
if ($type !== null) {
return $type;
}
@ -192,7 +192,7 @@ final class ConstructorPropertyTypeInferer extends AbstractTypeInferer implement
return false;
}
private function resolveFullyQualifiedOrAlaisedObjectType(Param $param): ?Type
private function resolveFullyQualifiedOrAliasedObjectType(Param $param): ?Type
{
if ($param->type === null) {
return null;
@ -216,7 +216,8 @@ final class ConstructorPropertyTypeInferer extends AbstractTypeInferer implement
return new FullyQualifiedObjectType($className);
}
return new AliasedObjectType($originalName->toString());
// @note: $fullyQualifiedName is a guess, needs real life test
return new AliasedObjectType($originalName->toString(), $fullyQualifiedName);
}
return null;

View File

@ -0,0 +1,18 @@
<?php
namespace Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropertyRector\Fixture;
use Rector\TypeDeclaration\Tests\Rector\Property\CompleteVarDocTypePropertyRector\Source\SomeService as SignalSlotDispatcher;
class SlotReplacement
{
/**
* @var SignalSlotDispatcher
*/
protected $signalSlotDispatcher;
public function __construct(SignalSlotDispatcher $signalSlotDispatcher)
{
$this->signalSlotDispatcher = $signalSlotDispatcher;
}
}