mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-25 20:32:35 +00:00
add property reflection resolver (#317)
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
f4ff000d45
commit
947da2c680
|
@ -271,7 +271,7 @@ final class PhpDocInfo
|
|||
|
||||
// FQN check
|
||||
$resolvedClass = $identifierTypeNode->getAttribute(PhpDocAttributeKey::RESOLVED_CLASS);
|
||||
if (!is_string($resolvedClass)) {
|
||||
if (! is_string($resolvedClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,8 @@ declare(strict_types=1);
|
|||
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;
|
||||
|
|
|
@ -10,7 +10,6 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
|||
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;
|
||||
|
|
|
@ -20,7 +20,6 @@ use Rector\Core\NodeManipulator\AssignManipulator;
|
|||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\ReadWrite\Guard\VariableToConstantGuard;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class ReadWritePropertyAnalyzer
|
||||
{
|
||||
|
@ -32,7 +31,7 @@ final class ReadWritePropertyAnalyzer
|
|||
) {
|
||||
}
|
||||
|
||||
public function isRead(PropertyFetch|StaticPropertyFetch $node): bool
|
||||
public function isRead(PropertyFetch | StaticPropertyFetch $node): bool
|
||||
{
|
||||
$parent = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $parent instanceof Node) {
|
||||
|
|
|
@ -10,7 +10,6 @@ use PhpParser\Node\Stmt\Interface_;
|
|||
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;
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace Rector\Defluent\NodeAnalyzer;
|
|||
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
use Rector\Core\Reflection\ReflectionResolver;
|
||||
use Rector\Defluent\Contract\ValueObject\FirstCallFactoryAwareInterface;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
|
|||
/**
|
||||
* @return Expr[]
|
||||
*/
|
||||
private function getNonVariableArguments(FuncCall|MethodCall|StaticCall $call): array
|
||||
private function getNonVariableArguments(FuncCall | MethodCall | StaticCall $call): array
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use PhpParser\Node\Expr\StaticCall;
|
|||
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:
|
||||
|
@ -31,8 +30,10 @@ final class IdentifierManipulator
|
|||
/**
|
||||
* @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;
|
||||
|
@ -41,8 +42,10 @@ final class IdentifierManipulator
|
|||
$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;
|
||||
|
|
|
@ -6,15 +6,13 @@ namespace Rector\TypeDeclaration\Rector\ClassMethod;
|
|||
|
||||
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;
|
||||
|
@ -26,7 +24,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
|||
final class ReturnTypeFromStrictTypedPropertyRector extends AbstractRector
|
||||
{
|
||||
public function __construct(
|
||||
private TypeFactory $typeFactory
|
||||
private TypeFactory $typeFactory,
|
||||
private ReflectionResolver $reflectionResolver
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -83,16 +82,11 @@ CODE_SAMPLE
|
|||
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) {
|
||||
|
@ -110,14 +104,15 @@ CODE_SAMPLE
|
|||
}
|
||||
|
||||
/**
|
||||
* @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 [];
|
||||
|
@ -127,16 +122,18 @@ CODE_SAMPLE
|
|||
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;
|
||||
|
|
|
@ -17,7 +17,6 @@ use PhpParser\Node\Stmt\Return_;
|
|||
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;
|
||||
|
|
|
@ -7,13 +7,14 @@ namespace Rector\Core\Reflection;
|
|||
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;
|
||||
|
@ -150,8 +151,44 @@ final class ReflectionResolver
|
|||
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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user