Skip to content

Commit

Permalink
[AutoImport] Add support for auto import in alias same last name (#2952)
Browse files Browse the repository at this point in the history
* [AutoImport] Add support for auto import in alias same last name

* implemented 🎉

* ensure alias not just renamed

* [ci-review] Rector Rectify

* final touch: add fixture for skip different fqcn

* really final touch: clean up

* add failing fixture

* more test

* stub unused

* progress

* Fix

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Sep 24, 2022
1 parent 429c9c0 commit 2015f46
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 13 deletions.
75 changes: 68 additions & 7 deletions packages/PostRector/Rector/NameImportingPostRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Rector\PostRector\Rector;

use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt;
Expand Down Expand Up @@ -120,10 +121,14 @@ private function processNodeName(Name $name, File $file): ?Node
$currentUses = $this->useImportsResolver->resolveForNode($name);

if ($this->shouldImportName($name, $currentUses)) {
$alias = $this->resolveAlias($name);
$nameInUse = $this->resolveNameInUse($name, $currentUses);

if ($alias instanceof Name) {
return $alias;
if ($nameInUse instanceof FullyQualified) {
return null;
}

if ($nameInUse instanceof Name) {
return $nameInUse;
}

return $this->nameImporter->importName($name, $file, $currentUses);
Expand All @@ -132,7 +137,10 @@ private function processNodeName(Name $name, File $file): ?Node
return null;
}

private function resolveAlias(Name $name): ?Name
/**
* @param Use_[]|GroupUse[] $currentUses
*/
private function resolveNameInUse(Name $name, array $currentUses): null|Name|FullyQualified
{
$originalName = $name->getAttribute(AttributeKey::ORIGINAL_NAME);

Expand All @@ -141,11 +149,64 @@ private function resolveAlias(Name $name): ?Name
}

$aliasName = $this->aliasNameResolver->resolveByName($name);
if (! is_string($aliasName)) {
return null;
if (is_string($aliasName)) {
return new Name($aliasName);
}

$isShortFullyQualifiedName = substr_count($name->toCodeString(), '\\') === 1;

if (! $isShortFullyQualifiedName) {
return $this->resolveLongNameInUseName($name, $currentUses);
}

return $this->resolveConflictedShortNameInUse($name, $currentUses);
}

/**
* @param Use_[]|GroupUse[] $currentUses
*/
private function resolveLongNameInUseName(Name $name, array $currentUses): ?Name
{
$lastName = $name->getLast();
foreach ($currentUses as $currentUse) {
foreach ($currentUse->uses as $useUse) {
if ($useUse->name->getLast() !== $lastName) {
continue;
}

if ($useUse->alias instanceof Identifier && $useUse->alias->toString() !== $lastName) {
return new Name($lastName);
}
}
}

return null;
}

/**
* @param Use_[]|GroupUse[] $currentUses
*/
private function resolveConflictedShortNameInUse(Name $name, array $currentUses): ?FullyQualified
{
$currentName = $name->toString();
foreach ($currentUses as $currentUse) {
$prefix = $this->useImportsResolver->resolvePrefix($currentUse);

foreach ($currentUse->uses as $useUse) {
$useName = $prefix . $name->toString();
$lastUseName = $name->getLast();

if (! $useUse->alias instanceof Identifier && $useName !== $currentName && $lastUseName === $currentName) {
return new FullyQualified($currentName);
}

if ($useUse->alias instanceof Identifier && $useUse->alias->toString() === $currentName) {
return new FullyQualified($currentName);
}
}
}

return new Name($aliasName);
return null;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions rules/CodingStyle/ClassNameImport/ClassNameImportSkipper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Rector\CodingStyle\ClassNameImport;

use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Use_;
Expand Down Expand Up @@ -96,6 +97,10 @@ public function isFoundInUse(Name $name, array $uses): bool
continue;
}

if ($useUse->alias instanceof Identifier && $useUse->alias->toString() === $nameLastName) {
continue;
}

return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,8 @@ private function processBinaryOp(Node $node): ?Expr
return null;
}

private function processBinaryPlusAndMinus(
\PhpParser\Node\Expr\BinaryOp\Plus | \PhpParser\Node\Expr\BinaryOp\Minus $binaryOp
): ?Expr {
private function processBinaryPlusAndMinus(Plus | Minus $binaryOp): ?Expr
{
if ($this->valueResolver->isValue($binaryOp->left, 0) && $this->nodeTypeResolver->isNumberType(
$binaryOp->right
)) {
Expand All @@ -158,9 +157,8 @@ private function processBinaryPlusAndMinus(
return $binaryOp->left;
}

private function processBinaryMulAndDiv(
\PhpParser\Node\Expr\BinaryOp\Mul | \PhpParser\Node\Expr\BinaryOp\Div $binaryOp
): ?Expr {
private function processBinaryMulAndDiv(Mul | Div $binaryOp): ?Expr
{
if ($binaryOp instanceof Mul && $this->valueResolver->isValue(
$binaryOp->left,
1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImportInAlias\Fixture;

use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\AssignOp\Plus as AssignPlus;

final class AutoImportInAliasSameLastName
{
public function run(\PhpParser\Node\Expr\BinaryOp\Plus $plus)
{
}

public function run2(AssignPlus $plus)
{
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\AutoImportInAlias\Fixture;

use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\AssignOp\Plus as AssignPlus;

final class AutoImportInAliasSameLastName
{
public function run(Plus $plus)
{
}

public function run2(AssignPlus $plus)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImportInAlias\Fixture;

use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\AssignOp\Plus as AssignPlus;

final class SkipAutoImportInAliasSameLastNameDifferentFqcn
{
public function run(\Rector\Core\Tests\Issues\AutoImportInAlias\Source\Plus $plus)
{
}

public function run2(AssignPlus $plus)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImportInAlias\Fixture;

use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\AssignOp\Plus as AssignPlus;

final class SkipAutoImportInAliasSameLastNameDifferentFqcn2
{
public function run(\Plus $plus)
{
}

public function run2(AssignPlus $plus)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImportInAlias\Fixture;

use PhpParser\Node\Expr\BinaryOp\Plus;
use PhpParser\Node\Expr\AssignOp\Plus as AssignPlus;

final class SkipAutoImportInAliasSameLastNameDifferentFqcn3
{
public function run(\Plus $plus)
{
}

public function run2(\AssignPlus $plus)
{
}
}

0 comments on commit 2015f46

Please sign in to comment.