Skip to content

Commit

Permalink
use ReflectionProvider instead of class_exists
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Feb 23, 2021
1 parent 9071f1b commit 3f80faa
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PHPStan\Reflection\Php\PhpPropertyReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Reflection\ReflectionProvider;
use Rector\DoctrineAnnotationGenerated\PhpDocNode\ConstantReferenceIdentifierRestorer;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
Expand Down Expand Up @@ -40,15 +43,21 @@ final class NodeAnnotationReader
* @var ConstantReferenceIdentifierRestorer
*/
private $constantReferenceIdentifierRestorer;
/**
* @var ReflectionProvider
*/
private $reflectionProvider;

public function __construct(
ConstantReferenceIdentifierRestorer $constantReferenceIdentifierRestorer,
NodeNameResolver $nodeNameResolver,
Reader $reader
Reader $reader,
ReflectionProvider $reflectionProvider
) {
$this->reader = $reader;
$this->nodeNameResolver = $nodeNameResolver;
$this->constantReferenceIdentifierRestorer = $constantReferenceIdentifierRestorer;
$this->reflectionProvider = $reflectionProvider;
}

public function readAnnotation(Node $node, string $annotationClass): ?object
Expand Down Expand Up @@ -87,13 +96,14 @@ public function readClassAnnotation(Class_ $class, string $annotationClassName):
public function readPropertyAnnotation(Property $property, string $annotationClassName): ?object
{
$propertyReflection = $this->createPropertyReflectionFromPropertyNode($property);
if (! $propertyReflection instanceof ReflectionProperty) {
if (! $propertyReflection instanceof PhpPropertyReflection) {
return null;
}

try {
// covers cases like https://github.com/rectorphp/rector/issues/3046

// @todo this will require original reflection
/** @var object[] $propertyAnnotations */
$propertyAnnotations = $this->reader->getPropertyAnnotations($propertyReflection);
return $this->matchNextAnnotation($propertyAnnotations, $annotationClassName, $property);
Expand Down Expand Up @@ -175,7 +185,7 @@ private function matchNextAnnotation(array $annotations, string $annotationClass
return null;
}

private function createPropertyReflectionFromPropertyNode(Property $property): ?ReflectionProperty
private function createPropertyReflectionFromPropertyNode(Property $property): ?PropertyReflection
{
/** @var string $propertyName */
$propertyName = $this->nodeNameResolver->getName($property);
Expand All @@ -186,13 +196,16 @@ private function createPropertyReflectionFromPropertyNode(Property $property): ?
// probably fresh node
return null;
}
if (! ClassExistenceStaticHelper::doesClassLikeExist($className)) {

if (! $this->reflectionProvider->hasClass($className)) {
// probably fresh node
return null;
}

try {
return new ReflectionProperty($className, $propertyName);
$classReflection = $this->reflectionProvider->getClass($className);
return $classReflection->getProperty($propertyName);
// return new ReflectionProperty($className, $propertyName);
} catch (Throwable $throwable) {
// in case of PHPUnit property or just-added property
return null;
Expand Down
11 changes: 9 additions & 2 deletions packages/static-type-mapper/src/PhpParser/NameNodeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Node;
use PhpParser\Node\Name;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
Expand All @@ -29,9 +30,15 @@ final class NameNodeMapper implements PhpParserNodeMapperInterface
*/
private $renamedClassesCollector;

public function __construct(RenamedClassesCollector $renamedClassesCollector)
/**
* @var ReflectionProvider
*/
private $reflectionProvider;

public function __construct(RenamedClassesCollector $renamedClassesCollector, ReflectionProvider $reflectionProvider)
{
$this->renamedClassesCollector = $renamedClassesCollector;
$this->reflectionProvider = $reflectionProvider;
}

public function getNodeType(): string
Expand All @@ -58,7 +65,7 @@ public function mapToPHPStan(Node $node): Type

private function isExistingClass(string $name): bool
{
if (ClassExistenceStaticHelper::doesClassLikeExist($name)) {
if ($this->reflectionProvider->hasClass($name)) {
return true;
}

Expand Down
20 changes: 14 additions & 6 deletions rules/renaming/src/NodeManipulator/ClassRenamer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\TypeAwareTagValueNodeInterface;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
Expand Down Expand Up @@ -70,14 +71,20 @@ final class ClassRenamer
*/
private $docBlockClassRenamer;

/**
* @var ReflectionProvider
*/
private $reflectionProvider;

public function __construct(
BetterNodeFinder $betterNodeFinder,
SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
ClassNaming $classNaming,
NodeNameResolver $nodeNameResolver,
PhpDocClassRenamer $phpDocClassRenamer,
PhpDocInfoFactory $phpDocInfoFactory,
DocBlockClassRenamer $docBlockClassRenamer
DocBlockClassRenamer $docBlockClassRenamer,
ReflectionProvider $reflectionProvider
) {
$this->nodeNameResolver = $nodeNameResolver;
$this->simpleCallableNodeTraverser = $simpleCallableNodeTraverser;
Expand All @@ -86,6 +93,7 @@ public function __construct(
$this->betterNodeFinder = $betterNodeFinder;
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->docBlockClassRenamer = $docBlockClassRenamer;
$this->reflectionProvider = $reflectionProvider;
}

/**
Expand Down Expand Up @@ -180,16 +188,16 @@ private function refactorNamespace(Namespace_ $namespace, array $oldToNewClasses
}

$currentName = $this->nodeNameResolver->getName($classLike);
$newClassFqn = $oldToNewClasses[$currentName];
$newClassFullyQualified = $oldToNewClasses[$currentName];

if (ClassExistenceStaticHelper::doesClassLikeExist($newClassFqn)) {
if ($this->reflectionProvider->hasClass($newClassFullyQualified)) {
return null;
}

$newNamespace = $this->classNaming->getNamespace($newClassFqn);
$newNamespace = $this->classNaming->getNamespace($newClassFullyQualified);
// Renaming to class without namespace (example MyNamespace\DateTime -> DateTimeImmutable)
if (! $newNamespace) {
$classLike->name = new Identifier($newClassFqn);
$classLike->name = new Identifier($newClassFullyQualified);

return $classLike;
}
Expand Down Expand Up @@ -362,7 +370,7 @@ private function isValidClassNameChange(Name $name, string $newName, Class_ $cla
return false;
}

if ($class->extends === $name && class_exists($newName)) {
if ($class->extends === $name && $this->reflectionProvider->hasClass($newName)) {
// is final class?
$reflectionClass = new ReflectionClass($newName);
if ($reflectionClass->isFinal()) {
Expand Down
11 changes: 9 additions & 2 deletions rules/restoration/src/NameMatcher/FullyQualifiedNameMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType;
use PhpParser\Node\UnionType;
use PHPStan\Reflection\ReflectionProvider;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;

Expand All @@ -24,10 +25,16 @@ final class FullyQualifiedNameMatcher
*/
private $nameMatcher;

public function __construct(NodeNameResolver $nodeNameResolver, NameMatcher $nameMatcher)
/**
* @var ReflectionProvider
*/
private $reflectionProvider;

public function __construct(NodeNameResolver $nodeNameResolver, NameMatcher $nameMatcher, ReflectionProvider $reflectionProvider)
{
$this->nodeNameResolver = $nodeNameResolver;
$this->nameMatcher = $nameMatcher;
$this->reflectionProvider = $reflectionProvider;
}

/**
Expand All @@ -51,7 +58,7 @@ public function matchFullyQualifiedName($name)
}

$resolvedName = $this->nodeNameResolver->getName($name);
if (ClassExistenceStaticHelper::doesClassLikeExist($resolvedName)) {
if ($this->reflectionProvider->hasClass($resolvedName)) {
return null;
}

Expand Down
20 changes: 16 additions & 4 deletions rules/type-declaration/src/PHPStan/Type/ObjectTypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
Expand All @@ -21,6 +22,16 @@

final class ObjectTypeSpecifier
{
/**
* @var ReflectionProvider
*/
private $reflectionProvider;

public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}

/**
* @return AliasedObjectType|FullyQualifiedObjectType|ObjectType|MixedType
*/
Expand Down Expand Up @@ -49,7 +60,8 @@ public function narrowToFullyQualifiedOrAliasedObjectType(Node $node, ObjectType
}

$className = ltrim($objectType->getClassName(), '\\');
if (ClassExistenceStaticHelper::doesClassLikeExist($className)) {

if ($this->reflectionProvider->hasClass($className)) {
return new FullyQualifiedObjectType($className);
}

Expand Down Expand Up @@ -160,7 +172,7 @@ private function matchSameNamespacedObjectType(Node $node, ObjectType $objectTyp

$namespacedObject = $namespaceName . '\\' . ltrim($objectType->getClassName(), '\\');

if (ClassExistenceStaticHelper::doesClassLikeExist($namespacedObject)) {
if ($this->reflectionProvider->hasClass($namespacedObject)) {
return new FullyQualifiedObjectType($namespacedObject);
}

Expand All @@ -177,7 +189,7 @@ private function matchPartialNamespaceObjectType(ObjectType $objectType, UseUse
$classNameWithoutLastUsePart = Strings::after($objectType->getClassName(), '\\', 1);

$connectedClassName = $useUse->name->toString() . '\\' . $classNameWithoutLastUsePart;
if (! ClassExistenceStaticHelper::doesClassLikeExist($connectedClassName)) {
if (!$this->reflectionProvider->hasClass($connectedClassName)) {
return null;
}

Expand All @@ -197,7 +209,7 @@ private function matchClassWithLastUseImportPart(ObjectType $objectType, UseUse
return null;
}

if (! ClassExistenceStaticHelper::doesClassLikeExist($useUse->name->toString())) {
if (! $this->reflectionProvider->hasClass($useUse->name->toString())) {
return null;
}

Expand Down

0 comments on commit 3f80faa

Please sign in to comment.