simplify ImportSkiport skip for ClassLike name

This commit is contained in:
TomasVotruba 2019-11-14 19:27:04 +01:00
parent b4cad2c679
commit a7b5e2f1e0
2 changed files with 58 additions and 61 deletions

View File

@ -6,12 +6,7 @@ namespace Rector\CodingStyle\Imports;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Interface_;
use Rector\CodingStyle\Application\UseAddingCommander;
use Rector\CodingStyle\Naming\ClassNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
final class ImportSkipper
@ -31,21 +26,14 @@ final class ImportSkipper
*/
private $shortNameResolver;
/**
* @var ClassNaming
*/
private $classNaming;
public function __construct(
UseAddingCommander $useAddingCommander,
AliasUsesResolver $aliasUsesResolver,
ShortNameResolver $shortNameResolver,
ClassNaming $classNaming
ShortNameResolver $shortNameResolver
) {
$this->useAddingCommander = $useAddingCommander;
$this->aliasUsesResolver = $aliasUsesResolver;
$this->shortNameResolver = $shortNameResolver;
$this->classNaming = $classNaming;
}
public function shouldSkipNameForFullyQualifiedObjectType(
@ -60,7 +48,7 @@ final class ImportSkipper
return true;
}
if ($this->isClassExtendsShortNameSameAsClassName($node, $fullyQualifiedObjectType)) {
if ($this->isNameAlreadyUsedInClassLikeName($node, $fullyQualifiedObjectType)) {
return true;
}
@ -100,53 +88,11 @@ final class ImportSkipper
return false;
}
private function isClassExtendsShortNameSameAsClassName(
private function isNameAlreadyUsedInClassLikeName(
Node $node,
FullyQualifiedObjectType $fullyQualifiedObjectType
): bool {
/** @var ClassLike|null $classLike */
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
if (! $classLike instanceof Class_ && ! $classLike instanceof Interface_) {
return false;
}
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof Class_) {
if ($parentNode->extends === $node) {
// are classLike and extends short name the same?
return $this->isClassLikeShortNameAndShortNameTypeEqual($fullyQualifiedObjectType, $classLike);
}
foreach ($parentNode->implements as $implement) {
if ($implement !== $node) {
continue;
}
return $this->isClassLikeShortNameAndShortNameTypeEqual($fullyQualifiedObjectType, $classLike);
}
}
if ($parentNode instanceof Interface_) {
foreach ($parentNode->extends as $extend) {
if ($extend !== $node) {
continue;
}
return $this->isClassLikeShortNameAndShortNameTypeEqual($fullyQualifiedObjectType, $classLike);
}
}
return false;
}
private function isClassLikeShortNameAndShortNameTypeEqual(
FullyQualifiedObjectType $fullyQualifiedObjectType,
ClassLike $classLike
): bool {
$shortClassName = $this->classNaming->getShortName($classLike->name);
$extendsShortName = $fullyQualifiedObjectType->getShortName();
return $shortClassName === $extendsShortName;
$classLikeNames = $this->shortNameResolver->resolveShortClassLikeNamesForNode($node);
return in_array($fullyQualifiedObjectType->getShortName(), $classLikeNames, true);
}
}

View File

@ -10,7 +10,9 @@ use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Namespace_;
use Rector\CodingStyle\Naming\ClassNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\Node\Resolver\NameResolver;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
final class ShortNameResolver
@ -25,9 +27,24 @@ final class ShortNameResolver
*/
private $shortNamesByNamespaceObjectHash = [];
public function __construct(CallableNodeTraverser $callableNodeTraverser)
{
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var ClassNaming
*/
private $classNaming;
public function __construct(
CallableNodeTraverser $callableNodeTraverser,
NameResolver $nameResolver,
ClassNaming $classNaming
) {
$this->callableNodeTraverser = $callableNodeTraverser;
$this->nameResolver = $nameResolver;
$this->classNaming = $classNaming;
}
/**
@ -38,6 +55,7 @@ final class ShortNameResolver
/** @var Namespace_|null $namespace */
$namespace = $node->getAttribute(AttributeKey::NAMESPACE_NODE);
if ($namespace === null) {
// only namespaced classes are supported
return [];
}
@ -53,6 +71,39 @@ final class ShortNameResolver
return $shortNames;
}
/**
* Collects all "class <SomeClass>", "trait <SomeTrait>" and "interface <SomeInterface>"
* @return string[]
*/
public function resolveShortClassLikeNamesForNode(Node $node): array
{
$namespace = $node->getAttribute(AttributeKey::NAMESPACE_NODE);
if ($namespace === null) {
// only handle namespace nodes
return [];
}
$shortClassLikeNames = [];
$this->callableNodeTraverser->traverseNodesWithCallable($namespace, function (Node $node) use (
&$shortClassLikeNames
) {
// ...
if (! $node instanceof ClassLike) {
return null;
}
if ($node->name === null) {
return null;
}
/** @var string $classLikeName */
$classLikeName = $this->nameResolver->getName($node->name);
$shortClassLikeNames[] = $this->classNaming->getShortName($classLikeName);
});
return array_unique($shortClassLikeNames);
}
/**
* @return string[]
*/