Skip to content

Commit

Permalink
[Core] Use FullyQualifiedObjectType and ThisType detection for local …
Browse files Browse the repository at this point in the history
…property fetch on PropertyFetchAnalyzer (#3172)
  • Loading branch information
samsonasik committed Dec 8, 2022
1 parent f8ad265 commit 2848e0d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@
namespace Rector\Naming\Rector\Foreach_;

use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Foreach_;
use PHPStan\Type\ThisType;
use Rector\CodeQuality\NodeAnalyzer\ForeachAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Naming\ExpectedNameResolver\InflectorSingularResolver;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

Expand Down Expand Up @@ -78,18 +73,12 @@ public function getNodeTypes(): array
*/
public function refactor(Node $node): ?Node
{
$isPropertyFetch = $this->propertyFetchAnalyzer->isPropertyFetch($node->expr);
$isPropertyFetch = $this->propertyFetchAnalyzer->isLocalPropertyFetch($node->expr);
if (! $node->expr instanceof Variable && ! $isPropertyFetch) {
return null;
}

/** @var Variable|PropertyFetch|StaticPropertyFetch $expr */
$expr = $node->expr;
if ($this->isNotCurrentClassLikePropertyFetch($expr, $isPropertyFetch)) {
return null;
}

$exprName = $this->getName($expr);
$exprName = $this->getName($node->expr);
if ($exprName === null) {
return null;
}
Expand Down Expand Up @@ -119,29 +108,6 @@ public function refactor(Node $node): ?Node
return $this->processRename($node, $valueVarName, $singularValueVarName);
}

private function isNotCurrentClassLikePropertyFetch(
PropertyFetch|StaticPropertyFetch|Variable $expr,
bool $isPropertyFetch
): bool {
if (! $isPropertyFetch) {
return false;
}

/** @var PropertyFetch|StaticPropertyFetch $expr */
$variableType = $expr instanceof PropertyFetch
? $this->nodeTypeResolver->getType($expr->var)
: $this->nodeTypeResolver->getType($expr->class);

if ($variableType instanceof FullyQualifiedObjectType) {
$currentClassLike = $this->betterNodeFinder->findParentType($expr, ClassLike::class);
if ($currentClassLike instanceof ClassLike) {
return ! $this->nodeNameResolver->isName($currentClassLike, $variableType->getClassName());
}
}

return ! $variableType instanceof ThisType;
}

private function processRename(Foreach_ $foreach, string $valueVarName, string $singularValueVarName): Foreach_
{
$foreach->valueVar = new Variable($singularValueVarName);
Expand Down
63 changes: 49 additions & 14 deletions src/NodeAnalyzer/PropertyFetchAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ThisType;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;

final class PropertyFetchAnalyzer
{
Expand All @@ -38,32 +42,39 @@ public function __construct(
private readonly NodeNameResolver $nodeNameResolver,
private readonly BetterNodeFinder $betterNodeFinder,
private readonly AstResolver $astResolver,
private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser
private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
private readonly NodeTypeResolver $nodeTypeResolver
) {
}

public function isLocalPropertyFetch(Node $node): bool
{
if ($node instanceof PropertyFetch) {
if (! $node->var instanceof Variable) {
return false;
}
if (! $node instanceof PropertyFetch && ! $node instanceof StaticPropertyFetch) {
return false;
}

return $this->nodeNameResolver->isName($node->var, self::THIS);
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
/**
* Property Fetch on Trait currently doesn't has Parent Node, so fallback to use this, self, static name instead
*/
if (! $parentNode instanceof Node) {
return $this->isTraitLocalPropertyFetch($node);
}

if ($node instanceof StaticPropertyFetch) {
if (! $node->class instanceof Name) {
return false;
$variableType = $node instanceof PropertyFetch
? $this->nodeTypeResolver->getType($node->var)
: $this->nodeTypeResolver->getType($node->class);

if ($variableType instanceof FullyQualifiedObjectType) {
$currentClassLike = $this->betterNodeFinder->findParentType($node, ClassLike::class);
if ($currentClassLike instanceof ClassLike) {
return $this->nodeNameResolver->isName($currentClassLike, $variableType->getClassName());
}

return $this->nodeNameResolver->isNames($node->class, [
ObjectReference::SELF,
ObjectReference::STATIC,
]);
return false;
}

return false;
return $variableType instanceof ThisType;
}

public function isLocalPropertyFetchName(Node $node, string $desiredPropertyName): bool
Expand Down Expand Up @@ -224,6 +235,30 @@ public function isLocalPropertyOfNames(Expr $expr, array $propertyNames): bool
return $this->nodeNameResolver->isNames($expr->name, $propertyNames);
}

private function isTraitLocalPropertyFetch(Node $node): bool
{
if ($node instanceof PropertyFetch) {
if (! $node->var instanceof Variable) {
return false;
}

return $this->nodeNameResolver->isName($node->var, self::THIS);
}

if ($node instanceof StaticPropertyFetch) {
if (! $node->class instanceof Name) {
return false;
}

return $this->nodeNameResolver->isNames($node->class, [
ObjectReference::SELF,
ObjectReference::STATIC,
]);
}

return false;
}

private function isPropertyAssignFoundInClassMethod(
ClassLike $classLike,
string $className,
Expand Down

0 comments on commit 2848e0d

Please sign in to comment.