[TypeDeclaration] Handle alias usage on FormerNullableArgumentToScalarTypedRector (#5408)

* Failing test case for Aliased class not found #5259

* Use existing class as aliased

* Close #5397 Fixes #5259

* clean up

* clean up

* non-namespaced patch

* use use name on method call/static call

* use use name on method call/static call

* phpstan

* phpstan

Co-authored-by: Michal Lulco <lulco@efabrica.sk>
This commit is contained in:
Abdul Malik Ikhsan 2021-02-02 21:17:04 +07:00 committed by GitHub
parent 931e233012
commit 44222174b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 8 deletions

View File

@ -6,6 +6,8 @@ namespace Rector\TypeDeclaration\PHPStan\Type;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PHPStan\Type\MixedType;
@ -63,6 +65,8 @@ final class ObjectTypeSpecifier
return null;
}
$className = $objectType->getClassName();
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
foreach ($uses as $use) {
foreach ($use->uses as $useUse) {
if ($useUse->alias === null) {
@ -73,14 +77,15 @@ final class ObjectTypeSpecifier
$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);
}
// B. is aliased classes matching the class name
if ($useName === $objectType->getClassName()) {
return new AliasedObjectType($alias, $fullyQualifiedName);
$processAliasedObject = $this->processAliasedObject(
$alias,
$className,
$useName,
$parentNode,
$fullyQualifiedName
);
if ($processAliasedObject instanceof AliasedObjectType) {
return $processAliasedObject;
}
}
}
@ -88,6 +93,31 @@ final class ObjectTypeSpecifier
return null;
}
private function processAliasedObject(
string $alias,
string $className,
string $useName,
?Node $parentNode,
string $fullyQualifiedName
): ?AliasedObjectType {
// A. is alias in use statement matching this class alias
if ($alias === $className) {
return new AliasedObjectType($alias, $fullyQualifiedName);
}
// B. is aliased classes matching the class name and parent node is MethodCall/StaticCall
if ($useName === $className && ($parentNode instanceof MethodCall || $parentNode instanceof StaticCall)) {
return new AliasedObjectType($useName, $fullyQualifiedName);
}
// C. is aliased classes matching the class name
if ($useName === $className) {
return new AliasedObjectType($alias, $fullyQualifiedName);
}
return null;
}
private function matchShortenedObjectType(Node $node, ObjectType $objectType): ?ShortenedObjectType
{
/** @var Use_[]|null $uses */

View File

@ -0,0 +1,33 @@
<?php
namespace Rector\TypeDeclaration\Tests\Rector\MethodCall\FormerNullableArgumentToScalarTypedRector\Fixture;
use Rector\TypeDeclaration\Tests\Rector\MethodCall\FormerNullableArgumentToScalarTypedRector\Source\NowString as NowStringAlias;
final class AliasedClass
{
public function run(NowStringAlias $nowString)
{
$nowString->setValue(null);
$nowString::setValue(null);
}
}
?>
-----
<?php
namespace Rector\TypeDeclaration\Tests\Rector\MethodCall\FormerNullableArgumentToScalarTypedRector\Fixture;
use Rector\TypeDeclaration\Tests\Rector\MethodCall\FormerNullableArgumentToScalarTypedRector\Source\NowString as NowStringAlias;
final class AliasedClass
{
public function run(NowStringAlias $nowString)
{
$nowString->setValue('');
$nowString::setValue('');
}
}
?>