Skip to content

Commit

Permalink
add property reflection resolver (#317)
Browse files Browse the repository at this point in the history
Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
TomasVotruba and actions-user committed Jun 27, 2021
1 parent f4ff000 commit 947da2c
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 39 deletions.
2 changes: 1 addition & 1 deletion packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public function getByAnnotationClass(string $desiredClass): ?DoctrineAnnotationT

// FQN check
$resolvedClass = $identifierTypeNode->getAttribute(PhpDocAttributeKey::RESOLVED_CLASS);
if (!is_string($resolvedClass)) {
if (! is_string($resolvedClass)) {
continue;
}

Expand Down
5 changes: 0 additions & 5 deletions packages/NodeCollector/NodeCollector/ParsedNodeCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
namespace Rector\NodeCollector\NodeCollector;

use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
use Rector\Core\Exception\ShouldNotHappenException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
use Rector\Core\Configuration\CurrentNodeProvider;
use Rector\Core\Configuration\RenamedClassesDataCollector;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\ValueObject\OldToNewType;
use Rector\StaticTypeMapper\StaticTypeMapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\ReadWrite\Guard\VariableToConstantGuard;
use Webmozart\Assert\Assert;

final class ReadWritePropertyAnalyzer
{
Expand All @@ -32,7 +31,7 @@ public function __construct(
) {
}

public function isRead(PropertyFetch|StaticPropertyFetch $node): bool
public function isRead(PropertyFetch | StaticPropertyFetch $node): bool
{
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
if (! $parent instanceof Node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use Rector\Core\NodeManipulator\PropertyManipulator;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Removing\NodeManipulator\ComplexNodeRemover;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use PhpParser\Node\Expr\MethodCall;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ReflectionProvider;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Defluent\Contract\ValueObject\FirstCallFactoryAwareInterface;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function refactor(Node $node): ?Node
/**
* @return Expr[]
*/
private function getNonVariableArguments(FuncCall|MethodCall|StaticCall $call): array
private function getNonVariableArguments(FuncCall | MethodCall | StaticCall $call): array
{
$arguments = [];

Expand Down
13 changes: 8 additions & 5 deletions rules/Renaming/NodeManipulator/IdentifierManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\NodeNameResolver\NodeNameResolver;
use Webmozart\Assert\Assert;

/**
* This class renames node identifier, e.g. ClassMethod rename:
Expand All @@ -31,8 +30,10 @@ public function __construct(
/**
* @param string[] $renameMethodMap
*/
public function renameNodeWithMap(ClassConstFetch|MethodCall|PropertyFetch|StaticCall|ClassMethod $node, array $renameMethodMap): void
{
public function renameNodeWithMap(
ClassConstFetch | MethodCall | PropertyFetch | StaticCall | ClassMethod $node,
array $renameMethodMap
): void {
$oldNodeMethodName = $this->resolveOldMethodName($node);
if ($oldNodeMethodName === null) {
return;
Expand All @@ -41,8 +42,10 @@ public function renameNodeWithMap(ClassConstFetch|MethodCall|PropertyFetch|Stati
$node->name = new Identifier($renameMethodMap[$oldNodeMethodName]);
}

public function removeSuffix(ClassConstFetch|MethodCall|PropertyFetch|StaticCall|ClassMethod $node, string $suffixToRemove): void
{
public function removeSuffix(
ClassConstFetch | MethodCall | PropertyFetch | StaticCall | ClassMethod $node,
string $suffixToRemove
): void {
$name = $this->nodeNameResolver->getName($node);
if ($name === null) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@

use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\UnionType;
use PHPStan\Reflection\Php\PhpPropertyReflection;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand All @@ -26,7 +24,8 @@
final class ReturnTypeFromStrictTypedPropertyRector extends AbstractRector
{
public function __construct(
private TypeFactory $typeFactory
private TypeFactory $typeFactory,
private ReflectionResolver $reflectionResolver
) {
}

Expand Down Expand Up @@ -83,16 +82,11 @@ public function refactor(Node $node): ?Node
return null;
}

$propertyTypeNodes = $this->resolveReturnPropertyTypeNodes($node);
if ($propertyTypeNodes === []) {
$propertyTypes = $this->resolveReturnPropertyType($node);
if ($propertyTypes === []) {
return null;
}

$propertyTypes = [];
foreach ($propertyTypeNodes as $propertyTypeNode) {
$propertyTypes[] = $this->staticTypeMapper->mapPhpParserNodePHPStanType($propertyTypeNode);
}

// add type to return type
$propertyType = $this->typeFactory->createMixedPassedOrUnionType($propertyTypes);
if ($propertyType instanceof MixedType) {
Expand All @@ -110,14 +104,15 @@ public function refactor(Node $node): ?Node
}

/**
* @return array<Identifier|Name|NullableType|UnionType>
* @return Type[]
*/
private function resolveReturnPropertyTypeNodes(ClassMethod $classMethod): array
private function resolveReturnPropertyType(ClassMethod $classMethod): array
{
/** @var Return_[] $returns */
$returns = $this->betterNodeFinder->findInstanceOf($classMethod, Return_::class);

$propertyTypes = [];

foreach ($returns as $return) {
if ($return->expr === null) {
return [];
Expand All @@ -127,16 +122,18 @@ private function resolveReturnPropertyTypeNodes(ClassMethod $classMethod): array
return [];
}

$property = $this->nodeRepository->findPropertyByPropertyFetch($return->expr);
if (! $property instanceof Property) {
$propertyReflection = $this->reflectionResolver->resolvePropertyReflectionFromPropertyFetch(
$return->expr
);
if (! $propertyReflection instanceof PhpPropertyReflection) {
return [];
}

if ($property->type === null) {
if ($propertyReflection->getNativeType() instanceof MixedType) {
return [];
}

$propertyTypes[] = $property->type;
$propertyTypes[] = $propertyReflection->getNativeType();
}

return $propertyTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use PhpParser\Node\Stmt\Trait_;
use PhpParser\NodeTraverser;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpFunctionReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
Expand Down
41 changes: 39 additions & 2 deletions src/Reflection/ReflectionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpPropertyReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
Expand Down Expand Up @@ -150,8 +151,44 @@ public function resolveMethodReflectionFromNew(New_ $new): ?MethodReflection
return $this->resolveMethodReflection($newClassType->getClassName(), MethodName::CONSTRUCT, $scope);
}

private function resolveFunctionReflectionFromFuncCall(FuncCall $funcCall): FunctionReflection | MethodReflection | null
public function resolvePropertyReflectionFromPropertyFetch(PropertyFetch $propertyFetch): ?PhpPropertyReflection
{
$fetcheeType = $this->nodeTypeResolver->resolve($propertyFetch->var);
if (! $fetcheeType instanceof TypeWithClassName) {
return null;
}

if (! $this->reflectionProvider->hasClass($fetcheeType->getClassName())) {
return null;
}

$classReflection = $this->reflectionProvider->getClass($fetcheeType->getClassName());

$propertyName = $this->nodeNameResolver->getName($propertyFetch->name);
if ($propertyName === null) {
return null;
}

if (! $classReflection->hasProperty($propertyName)) {
return null;
}

$scope = $propertyFetch->getAttribute(AttributeKey::SCOPE);
if ($scope instanceof Scope) {
$propertyRelfection = $classReflection->getProperty($propertyName, $scope);
if ($propertyRelfection instanceof PhpPropertyReflection) {
return $propertyRelfection;
}

return null;
}

return $classReflection->getNativeProperty($propertyName);
}

private function resolveFunctionReflectionFromFuncCall(
FuncCall $funcCall
): FunctionReflection | MethodReflection | null {
$scope = $funcCall->getAttribute(AttributeKey::SCOPE);

if ($funcCall->name instanceof Name) {
Expand Down

0 comments on commit 947da2c

Please sign in to comment.