Merge branch 'master' into phpstan-fixes

This commit is contained in:
Tomas Votruba 2020-02-09 12:16:28 +01:00 committed by GitHub
commit 6f397bade5
54 changed files with 1166 additions and 1023 deletions

View File

@ -75,6 +75,9 @@ parameters:
# @todo resolve!!!
Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff:
- 'src/NodeContainer/NodeCollector/ParsedFunctionLikeNodesByType.php'
- 'src/NodeContainer/NodeCollector/ParsedFunctionLikeNodeCollector.php'
- 'packages/solid/src/Rector/ClassConst/PrivatizeLocalClassConstantRector.php'
- 'packages/type-declaration/src/TypeInferer/PropertyTypeInferer/ConstructorPropertyTypeInferer.php'
- 'packages/node-type-resolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php'
- 'packages/minimal-scope/src/Rector/Class_/ChangeLocalPropertyToVariableRector.php'

View File

@ -9,7 +9,7 @@ use PhpParser\Node\Stmt\Property;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocNode\JMS\SerializerTypeTagValueNode;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
@ -26,23 +26,23 @@ final class ClassAnalyzer
*/
private $nameResolver;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
NameResolver $nameResolver,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
NodeTypeResolver $nodeTypeResolver
) {
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->nodeTypeResolver = $nodeTypeResolver;
}
@ -81,7 +81,7 @@ final class ClassAnalyzer
// awesome!
// is it services or value object?
$paramTypeClass = $this->parsedNodesByType->findClass($paramType->getClassName());
$paramTypeClass = $this->parsedNodeCollector->findClass($paramType->getClassName());
if ($paramTypeClass === null) {
// not sure :/
continue;

View File

@ -21,7 +21,6 @@ use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -36,16 +35,6 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
*/
final class CallableThisArrayToAnonymousFunctionRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Convert [$this, "method"] to proper anonymous function', [
@ -158,7 +147,7 @@ PHP
$objectType = $this->getObjectType($objectExpr);
if ($objectType instanceof ObjectType) {
$class = $this->parsedNodesByType->findClass($objectType->getClassName());
$class = $this->classLikeParsedNodesFinder->findClass($objectType->getClassName());
if ($class === null) {
return null;

View File

@ -15,7 +15,6 @@ use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
@ -29,19 +28,13 @@ use ReflectionMethod;
*/
final class RemoveDelegatingParentCallRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ValueResolver
*/
private $valueResolver;
public function __construct(ParsedNodesByType $parsedNodesByType, ValueResolver $valueResolver)
public function __construct(ValueResolver $valueResolver)
{
$this->parsedNodesByType = $parsedNodesByType;
$this->valueResolver = $valueResolver;
}
@ -229,7 +222,7 @@ PHP
/** @var string $methodName */
$methodName = $this->getName($staticCall);
$parentClassMethod = $this->parsedNodesByType->findMethod($methodName, $parentClassName);
$parentClassMethod = $this->functionLikeParsedNodesFinder->findMethod($methodName, $parentClassName);
if ($parentClassMethod !== null) {
if ($parentClassMethod->isProtected() && $classMethod->isPublic()) {
return true;

View File

@ -9,7 +9,6 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -20,16 +19,6 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
*/
final class RemoveUnusedPrivateMethodRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove unused private method', [
@ -79,7 +68,7 @@ PHP
return null;
}
$classMethodCalls = $this->parsedNodesByType->findClassMethodCalls($node);
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($node);
if ($classMethodCalls !== []) {
return null;
}

View File

@ -11,7 +11,6 @@ use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
@ -31,11 +30,6 @@ final class RemoveUnusedDoctrineEntityMethodAndPropertyRector extends AbstractRe
*/
private $collectionByPropertyName = [];
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ClassUnusedPrivateClassMethodResolver
*/
@ -52,12 +46,10 @@ final class RemoveUnusedDoctrineEntityMethodAndPropertyRector extends AbstractRe
private $doctrineEntityManipulator;
public function __construct(
ParsedNodesByType $parsedNodesByType,
ClassUnusedPrivateClassMethodResolver $classUnusedPrivateClassMethodResolver,
ClassManipulator $classManipulator,
DoctrineEntityManipulator $doctrineEntityManipulator
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->classUnusedPrivateClassMethodResolver = $classUnusedPrivateClassMethodResolver;
$this->classManipulator = $classManipulator;
$this->doctrineEntityManipulator = $doctrineEntityManipulator;
@ -265,7 +257,7 @@ PHP
}
// get the class property and remove "mappedBy/inversedBy" from annotation
$relatedEntityClass = $this->parsedNodesByType->findClass($targetEntity);
$relatedEntityClass = $this->classLikeParsedNodesFinder->findClass($targetEntity);
if (! $relatedEntityClass instanceof Class_) {
return null;
}

View File

@ -11,7 +11,6 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\FunctionLike;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -23,16 +22,6 @@ use ReflectionFunction;
*/
final class RemoveDefaultArgumentValueRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Remove argument value, if it is the same as default value', [
@ -159,7 +148,7 @@ PHP
return [];
}
$classMethodNode = $this->parsedNodesByType->findMethod($nodeName, $className);
$classMethodNode = $this->functionLikeParsedNodesFinder->findMethod($nodeName, $className);
if ($classMethodNode !== null) {
return $this->resolveDefaultParamValuesFromFunctionLike($classMethodNode);
}
@ -207,7 +196,7 @@ PHP
*/
private function resolveFuncCallDefaultParamValues(string $nodeName): array
{
$functionNode = $this->parsedNodesByType->findFunction($nodeName);
$functionNode = $this->functionLikeParsedNodesFinder->findFunction($nodeName);
if ($functionNode !== null) {
return $this->resolveDefaultParamValuesFromFunctionLike($functionNode);
}

View File

@ -6,7 +6,7 @@ namespace Rector\DeadCode\UnusedNodeResolver;
use Nette\Utils\Strings;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeFinder\FunctionLikeParsedNodesFinder;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use ReflectionMethod;
@ -18,24 +18,24 @@ final class ClassUnusedPrivateClassMethodResolver
*/
private $nameResolver;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ClassManipulator
*/
private $classManipulator;
/**
* @var FunctionLikeParsedNodesFinder
*/
private $functionLikeParsedNodesFinder;
public function __construct(
NameResolver $nameResolver,
ParsedNodesByType $parsedNodesByType,
ClassManipulator $classManipulator
ClassManipulator $classManipulator,
FunctionLikeParsedNodesFinder $functionLikeParsedNodesFinder
) {
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->classManipulator = $classManipulator;
$this->functionLikeParsedNodesFinder = $functionLikeParsedNodesFinder;
}
/**
@ -45,7 +45,8 @@ final class ClassUnusedPrivateClassMethodResolver
{
/** @var string $className */
$className = $this->nameResolver->getName($class);
$classMethodCalls = $this->parsedNodesByType->findMethodCallsOnClass($className);
$classMethodCalls = $this->functionLikeParsedNodesFinder->findMethodCallsOnClass($className);
$usedMethodNames = array_keys($classMethodCalls);
$classPublicMethodNames = $this->classManipulator->getPublicMethodNames($class);

View File

@ -13,7 +13,7 @@ use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Exception\NotImplementedException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\Testing\PHPUnit\PHPUnitEnvironment;
@ -30,14 +30,14 @@ final class UnusedClassResolver
private $nameResolver;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
public function __construct(NameResolver $nameResolver, ParsedNodesByType $parsedNodesByType)
public function __construct(NameResolver $nameResolver, ParsedNodeCollector $parsedNodeCollector)
{
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
}
/**
@ -90,7 +90,7 @@ final class UnusedClassResolver
$classNames = [];
/** @var Param[] $paramNodes */
$paramNodes = $this->parsedNodesByType->getNodesByType(Param::class);
$paramNodes = $this->parsedNodeCollector->getNodesByType(Param::class);
foreach ($paramNodes as $paramNode) {
if ($paramNode->type === null) {
continue;
@ -124,7 +124,7 @@ final class UnusedClassResolver
$classNames = [];
/** @var New_[] $newNodes */
$newNodes = $this->parsedNodesByType->getNodesByType(New_::class);
$newNodes = $this->parsedNodeCollector->getNodesByType(New_::class);
foreach ($newNodes as $newNode) {
$newNodeClassName = $this->nameResolver->getName($newNode->class);
if (! is_string($newNodeClassName)) {
@ -145,7 +145,7 @@ final class UnusedClassResolver
$classNames = [];
/** @var StaticCall[] $staticCallNodes */
$staticCallNodes = $this->parsedNodesByType->getNodesByType(StaticCall::class);
$staticCallNodes = $this->parsedNodeCollector->getNodesByType(StaticCall::class);
foreach ($staticCallNodes as $staticCallNode) {
$staticClassName = $this->nameResolver->getName($staticCallNode->class);
if (! is_string($staticClassName)) {
@ -163,7 +163,7 @@ final class UnusedClassResolver
private function getClassConstantFetchNames(): array
{
/** @var ClassConstFetch[] $classConstFetches */
$classConstFetches = $this->parsedNodesByType->getNodesByType(ClassConstFetch::class);
$classConstFetches = $this->parsedNodeCollector->getNodesByType(ClassConstFetch::class);
$classNames = [];
foreach ($classConstFetches as $classConstFetch) {

View File

@ -14,7 +14,7 @@ use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\IdTagValueNode;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
use Rector\NodeTypeResolver\Node\AttributeKey;
use ReflectionClass;
@ -22,13 +22,13 @@ use ReflectionClass;
final class DoctrineDocBlockResolver
{
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
public function __construct(ParsedNodesByType $parsedNodesByType)
public function __construct(ParsedNodeCollector $parsedNodeCollector)
{
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
}
/**
@ -47,7 +47,7 @@ final class DoctrineDocBlockResolver
if (is_string($class)) {
if (ClassExistenceStaticHelper::doesClassLikeExist($class)) {
$classNode = $this->parsedNodesByType->findClass($class);
$classNode = $this->parsedNodeCollector->findClass($class);
if ($classNode !== null) {
return $this->isDoctrineEntityClass($classNode);
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\IdTagValueNode;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Doctrine\PhpDocParser\DoctrineDocBlockResolver;
@ -24,9 +24,9 @@ final class EntityWithMissingUuidProvider
private $entitiesWithMissingUuidProperty = [];
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
/**
* @var DoctrineDocBlockResolver
@ -44,12 +44,12 @@ final class EntityWithMissingUuidProvider
private $nameResolver;
public function __construct(
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
DoctrineDocBlockResolver $doctrineDocBlockResolver,
ClassManipulator $classManipulator,
NameResolver $nameResolver
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->doctrineDocBlockResolver = $doctrineDocBlockResolver;
$this->classManipulator = $classManipulator;
$this->nameResolver = $nameResolver;
@ -65,7 +65,7 @@ final class EntityWithMissingUuidProvider
}
$entitiesWithMissingUuidProperty = [];
foreach ($this->parsedNodesByType->getClasses() as $class) {
foreach ($this->parsedNodeCollector->getClasses() as $class) {
if (! $this->doctrineDocBlockResolver->isDoctrineEntityClassWithIdProperty($class)) {
continue;
}

View File

@ -13,7 +13,6 @@ use PhpParser\Node\Stmt\Expression;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use Ramsey\Uuid\Uuid;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -27,21 +26,13 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
*/
final class ChangeSetIdToUuidValueRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var DoctrineEntityManipulator
*/
private $doctrineEntityManipulator;
public function __construct(
ParsedNodesByType $parsedNodesByType,
DoctrineEntityManipulator $doctrineEntityManipulator
) {
$this->parsedNodesByType = $parsedNodesByType;
public function __construct(DoctrineEntityManipulator $doctrineEntityManipulator)
{
$this->doctrineEntityManipulator = $doctrineEntityManipulator;
}
@ -123,7 +114,7 @@ PHP
// B. is the value constant reference?
$argumentValue = $node->args[0]->value;
if ($argumentValue instanceof ClassConstFetch) {
$classConst = $this->parsedNodesByType->findClassConstantByClassConstFetch($argumentValue);
$classConst = $this->parsedNodeCollector->findClassConstantByClassConstFetch($argumentValue);
if ($classConst === null) {
return null;
}

View File

@ -13,7 +13,6 @@ use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Return_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -40,15 +39,9 @@ final class RenameEventNamesInEventSubscriberRector extends AbstractRector
*/
private $symfonyClassConstWithAliases = [];
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(EventInfosFactory $eventInfosFactory, ParsedNodesByType $parsedNodesByType)
public function __construct(EventInfosFactory $eventInfosFactory)
{
$this->symfonyClassConstWithAliases = $eventInfosFactory->create();
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
@ -184,7 +177,7 @@ PHP
private function processMethodArgument(string $class, string $method, EventInfo $eventInfo): void
{
$classMethodNode = $this->parsedNodesByType->findMethod($method, $class);
$classMethodNode = $this->functionLikeParsedNodesFinder->findMethod($method, $class);
if ($classMethodNode === null) {
return;
}

View File

@ -15,7 +15,6 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocNode\Symfony\SymfonyRouteTagValueNode;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -35,11 +34,6 @@ use ReflectionMethod;
*/
final class RouterListToControllerAnnotationsRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var RouteInfoFactory
*/
@ -56,12 +50,10 @@ final class RouterListToControllerAnnotationsRector extends AbstractRector
private $implicitToExplicitRoutingAnnotationDecorator;
public function __construct(
ParsedNodesByType $parsedNodesByType,
RouteInfoFactory $routeInfoFactory,
ReturnTypeInferer $returnTypeInferer,
ImplicitToExplicitRoutingAnnotationDecorator $implicitToExplicitRoutingAnnotationDecorator
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->routeInfoFactory = $routeInfoFactory;
$this->returnTypeInferer = $returnTypeInferer;
$this->implicitToExplicitRoutingAnnotationDecorator = $implicitToExplicitRoutingAnnotationDecorator;
@ -236,7 +228,7 @@ PHP
private function resolveControllerClassMethod(RouteInfo $routeInfo): ?ClassMethod
{
$classNode = $this->parsedNodesByType->findClass($routeInfo->getClass());
$classNode = $this->classLikeParsedNodesFinder->findClass($routeInfo->getClass());
if ($classNode === null) {
return null;
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\String_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
use Rector\NetteToSymfony\ValueObject\RouteInfo;
@ -28,18 +28,18 @@ final class RouteInfoFactory
private $valueResolver;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
public function __construct(
NameResolver $nameResolver,
ValueResolver $valueResolver,
ParsedNodesByType $parsedNodesByType
ParsedNodeCollector $parsedNodeCollector
) {
$this->nameResolver = $nameResolver;
$this->valueResolver = $valueResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
}
public function createFromNode(Node $node): ?RouteInfo
@ -127,9 +127,9 @@ final class RouteInfoFactory
// detect class by controller name?
// foreach all instance and try to match a name $controller . 'Presenter/Controller'
$classNode = $this->parsedNodesByType->findByShortName($controller . 'Presenter');
$classNode = $this->parsedNodeCollector->findByShortName($controller . 'Presenter');
if ($classNode === null) {
$classNode = $this->parsedNodesByType->findByShortName($controller . 'Controller');
$classNode = $this->parsedNodeCollector->findByShortName($controller . 'Controller');
}
// unable to find here

View File

@ -31,7 +31,7 @@ use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -74,9 +74,9 @@ final class NodeTypeResolver
private $objectTypeSpecifier;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
/**
* @var BetterPhpDocParser
@ -99,7 +99,7 @@ final class NodeTypeResolver
public function __construct(
BetterPhpDocParser $betterPhpDocParser,
NameResolver $nameResolver,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
ClassReflectionTypesResolver $classReflectionTypesResolver,
ReflectionProvider $reflectionProvider,
TypeFactory $typeFactory,
@ -117,7 +117,7 @@ final class NodeTypeResolver
$this->reflectionProvider = $reflectionProvider;
$this->typeFactory = $typeFactory;
$this->objectTypeSpecifier = $objectTypeSpecifier;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->betterPhpDocParser = $betterPhpDocParser;
$this->staticTypeMapper = $staticTypeMapper;
}
@ -455,7 +455,7 @@ final class NodeTypeResolver
return null;
}
if ($this->parsedNodesByType->findClass($varObjectType->getClassName()) !== null) {
if ($this->parsedNodeCollector->findClass($varObjectType->getClassName()) !== null) {
return null;
}

View File

@ -6,18 +6,27 @@ namespace Rector\NodeTypeResolver\NodeVisitor;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedFunctionLikeNodeCollector;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
final class NodeCollectorNodeVisitor extends NodeVisitorAbstract
{
/**
* @var ParsedNodesByType
* @var ParsedFunctionLikeNodeCollector
*/
private $parsedNodesByType;
private $parsedFunctionLikeNodeCollector;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
ParsedNodeCollector $parsedNodeCollector,
ParsedFunctionLikeNodeCollector $parsedFunctionLikeNodeCollector
) {
$this->parsedFunctionLikeNodeCollector = $parsedFunctionLikeNodeCollector;
$this->parsedNodeCollector = $parsedNodeCollector;
}
/**
@ -25,10 +34,10 @@ final class NodeCollectorNodeVisitor extends NodeVisitorAbstract
*/
public function enterNode(Node $node)
{
if (! $this->parsedNodesByType->isCollectableNode($node)) {
return;
if ($this->parsedNodeCollector->isCollectableNode($node)) {
$this->parsedNodeCollector->collect($node);
}
$this->parsedNodesByType->collect($node);
$this->parsedFunctionLikeNodeCollector->collect($node);
}
}

View File

@ -8,7 +8,6 @@ use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PHPUnit\Framework\TestCase;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -20,16 +19,6 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
*/
final class ThisCallOnStaticMethodToStaticCallRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Changes $this->call() to static method to static call', [
@ -100,7 +89,7 @@ PHP
return null;
}
$isStaticMethod = $this->parsedNodesByType->isStaticMethod($methodName, $className);
$isStaticMethod = $this->functionLikeParsedNodesFinder->isStaticMethod($methodName, $className);
if (! $isStaticMethod) {
return null;
}

View File

@ -10,7 +10,6 @@ use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PHPStan\Type\ObjectType;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\PhpParser\Node\Manipulator\ClassMethodManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
@ -27,21 +26,13 @@ use ReflectionClass;
*/
final class StaticCallOnNonStaticToInstanceCallRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ClassMethodManipulator
*/
private $classMethodManipulator;
public function __construct(
ParsedNodesByType $parsedNodesByType,
ClassMethodManipulator $classMethodManipulator
) {
$this->parsedNodesByType = $parsedNodesByType;
public function __construct(ClassMethodManipulator $classMethodManipulator)
{
$this->classMethodManipulator = $classMethodManipulator;
}
@ -106,7 +97,7 @@ PHP
return null;
}
$isStaticMethod = $this->parsedNodesByType->isStaticMethod($methodName, $className);
$isStaticMethod = $this->functionLikeParsedNodesFinder->isStaticMethod($methodName, $className);
if ($isStaticMethod) {
return null;
}
@ -131,7 +122,7 @@ PHP
}
// can we add static to method?
$classMethodNode = $this->parsedNodesByType->findMethod($methodName, $className);
$classMethodNode = $this->functionLikeParsedNodesFinder->findMethod($methodName, $className);
if ($classMethodNode === null) {
return null;
}

View File

@ -13,13 +13,11 @@ use PhpParser\Node\Stmt\Class_;
use PHPStan\Type\ObjectType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Naming\PropertyNaming;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
use Rector\RemovingStatic\StaticTypesInClassResolver;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
/**
* Depends on @see PassFactoryToUniqueObjectRector
@ -48,36 +46,22 @@ final class NewUniqueObjectToEntityFactoryRector extends AbstractRector
*/
private $propertyNaming;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var StaticTypesInClassResolver
*/
private $staticTypesInClassResolver;
/**
* @var PrivatesAccessor
*/
private $privatesAccessor;
/**
* @param string[] $typesToServices
*/
public function __construct(
PropertyNaming $propertyNaming,
ParsedNodesByType $parsedNodesByType,
StaticTypesInClassResolver $staticTypesInClassResolver,
PrivatesAccessor $privatesAccessor,
array $typesToServices = []
) {
$this->typesToServices = $typesToServices;
$this->propertyNaming = $propertyNaming;
$this->parsedNodesByType = $parsedNodesByType;
$this->staticTypesInClassResolver = $staticTypesInClassResolver;
$this->privatesAccessor = $privatesAccessor;
}
public function getDefinition(): RectorDefinition
@ -188,7 +172,7 @@ PHP
}
// temporary
$classes = $this->privatesAccessor->getPrivateProperty($this->parsedNodesByType, 'classes');
$classes = $this->parsedNodeCollector->getClasses();
if ($classes === []) {
return [];
}

View File

@ -7,3 +7,4 @@ services:
resource: '../src'
exclude:
- '../src/Rector/**/*Rector.php'
- '../src/ValueObject/*'

View File

@ -8,7 +8,7 @@ use PhpParser\Node\Expr\ClassConstFetch;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeUtils;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\Testing\PHPUnit\PHPUnitEnvironment;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -21,11 +21,6 @@ final class ClassConstantFetchAnalyzer
*/
private $classConstantFetchByClassAndName = [];
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var NameResolver
*/
@ -36,14 +31,19 @@ final class ClassConstantFetchAnalyzer
*/
private $nodeTypeResolver;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
ParsedNodesByType $parsedNodesByType,
NodeTypeResolver $nodeTypeResolver,
NameResolver $nameResolver
NameResolver $nameResolver,
ParsedNodeCollector $parsedNodeCollector
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->nodeTypeResolver = $nodeTypeResolver;
$this->nameResolver = $nameResolver;
$this->parsedNodeCollector = $parsedNodeCollector;
}
/**
@ -56,7 +56,7 @@ final class ClassConstantFetchAnalyzer
return $this->classConstantFetchByClassAndName;
}
$classConstFetches = $this->parsedNodesByType->getNodesByType(ClassConstFetch::class);
$classConstFetches = $this->parsedNodeCollector->getNodesByType(ClassConstFetch::class);
foreach ($classConstFetches as $classConstantFetch) {
$this->addClassConstantFetch($classConstantFetch);
}
@ -99,7 +99,7 @@ final class ClassConstantFetchAnalyzer
$classNames = TypeUtils::getDirectClassNames($type);
foreach ($classNames as $className) {
$classOrInterface = $this->parsedNodesByType->findClassOrInterface($className);
$classOrInterface = $this->parsedNodeCollector->findClassOrInterface($className);
if ($classOrInterface === null) {
continue;
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Rector\SOLID\NodeFinder;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class ParentClassConstantNodeFinder
{
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(ParsedNodeCollector $parsedNodeCollector)
{
$this->parsedNodeCollector = $parsedNodeCollector;
}
public function find(string $class, string $constant): ?ClassConst
{
$classNode = $this->parsedNodeCollector->findClass($class);
if ($classNode === null) {
return null;
}
/** @var string|null $parentClassName */
$parentClassName = $classNode->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName === null) {
return null;
}
return $this->parsedNodeCollector->findClassConstant($parentClassName, $constant);
}
}

View File

@ -6,12 +6,15 @@ namespace Rector\SOLID\Rector\ClassConst;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\SOLID\Analyzer\ClassConstantFetchAnalyzer;
use Rector\SOLID\NodeFinder\ParentClassConstantNodeFinder;
use Rector\SOLID\Reflection\ParentConstantReflectionResolver;
use Rector\SOLID\ValueObject\ConstantVisibility;
/**
* @see \Rector\SOLID\Tests\Rector\ClassConst\PrivatizeLocalClassConstantRector\PrivatizeLocalClassConstantRectorTest
@ -23,22 +26,29 @@ final class PrivatizeLocalClassConstantRector extends AbstractRector
*/
public const HAS_NEW_ACCESS_LEVEL = 'has_new_access_level';
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ClassConstantFetchAnalyzer
*/
private $classConstantFetchAnalyzer;
/**
* @var ParentConstantReflectionResolver
*/
private $parentConstantReflectionResolver;
/**
* @var ParentClassConstantNodeFinder
*/
private $parentClassConstantNodeFinder;
public function __construct(
ParsedNodesByType $parsedNodesByType,
ClassConstantFetchAnalyzer $classConstantFetchAnalyzer
ClassConstantFetchAnalyzer $classConstantFetchAnalyzer,
ParentConstantReflectionResolver $parentConstantReflectionResolver,
ParentClassConstantNodeFinder $parentClassConstantNodeFinder
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->classConstantFetchAnalyzer = $classConstantFetchAnalyzer;
$this->parentConstantReflectionResolver = $parentConstantReflectionResolver;
$this->parentClassConstantNodeFinder = $parentClassConstantNodeFinder;
}
public function getDefinition(): RectorDefinition
@ -96,29 +106,25 @@ PHP
$class = $node->getAttribute(AttributeKey::CLASS_NAME);
// 0. constants declared in interfaces have to be public
if ($this->parsedNodesByType->findInterface($class) !== null) {
if ($this->classLikeParsedNodesFinder->findInterface($class) !== null) {
$this->makePublic($node);
return $node;
}
/** @var string $constant */
$constant = $this->getName($node);
$parentConstIsProtected = false;
$parentClassConstant = $this->findParentClassConstant($class, $constant);
if ($parentClassConstant !== null) {
// The parent's constant is public, so this one must become public too
if ($parentClassConstant->isPublic()) {
$this->makePublic($node);
return $node;
}
$parentClassConstantVisibility = $this->findParentClassConstantAndRefactorIfPossible($class, $constant);
$parentConstIsProtected = $parentClassConstant->isProtected();
// The parent's constant is public, so this one must become public too
if ($parentClassConstantVisibility !== null && $parentClassConstantVisibility->isPublic()) {
$this->makePublic($node);
return $node;
}
$useClasses = $this->findClassConstantFetches($class, $constant);
return $this->changeConstantVisibility($node, $useClasses, $parentConstIsProtected, $class);
return $this->changeConstantVisibility($node, $useClasses, $parentClassConstantVisibility, $class);
}
private function shouldSkip(ClassConst $classConst): bool
@ -127,33 +133,39 @@ PHP
return true;
}
if (! $this->isAtLeastPhpVersion('7.1')) {
if (! $this->isAtLeastPhpVersion(PhpVersionFeature::CONSTANT_VISIBILITY)) {
return true;
}
return count($classConst->consts) !== 1;
}
private function findParentClassConstant(string $class, string $constant): ?ClassConst
private function findParentClassConstantAndRefactorIfPossible(string $class, string $constant): ?ConstantVisibility
{
$classNode = $this->parsedNodesByType->findClass($class);
if ($classNode !== null && $classNode->hasAttribute(AttributeKey::PARENT_CLASS_NAME)) {
/** @var string $parentClassName */
$parentClassName = $classNode->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== '') {
$parentClassConstant = $this->parsedNodesByType->findClassConstant($parentClassName, $constant);
if ($parentClassConstant !== null) {
// Make sure the parent's constant has been refactored
$this->refactor($parentClassConstant);
$parentClassConstant = $this->parentClassConstantNodeFinder->find($class, $constant);
return $parentClassConstant;
}
// If the constant isn't declared in the parent, it might be declared in the parent's parent
return $this->findParentClassConstant($parentClassName, $constant);
}
if ($parentClassConstant !== null) {
// Make sure the parent's constant has been refactored
$this->refactor($parentClassConstant);
return new ConstantVisibility(
$parentClassConstant->isPublic(),
$parentClassConstant->isProtected(),
$parentClassConstant->isPrivate()
);
// If the constant isn't declared in the parent, it might be declared in the parent's parent
}
return null;
$parentClassConstantReflection = $this->parentConstantReflectionResolver->resolve($class, $constant);
if ($parentClassConstantReflection === null) {
return null;
}
return new ConstantVisibility(
$parentClassConstantReflection->isPublic(),
$parentClassConstantReflection->isProtected(),
$parentClassConstantReflection->isPrivate()
);
}
private function findClassConstantFetches(string $className, string $constantName): ?array
@ -169,18 +181,18 @@ PHP
private function changeConstantVisibility(
ClassConst $classConst,
?array $useClasses,
bool $parentConstIsProtected,
?ConstantVisibility $constantVisibility,
string $class
): Node {
// 1. is actually never used (@todo use in "dead-code" set)
if ($useClasses === null) {
$this->makePrivateOrWeaker($classConst, $parentConstIsProtected);
$this->makePrivateOrWeaker($classConst, $constantVisibility);
return $classConst;
}
// 2. is only local use? → private
if ($useClasses === [$class]) {
$this->makePrivateOrWeaker($classConst, $parentConstIsProtected);
$this->makePrivateOrWeaker($classConst, $constantVisibility);
return $classConst;
}
@ -194,11 +206,13 @@ PHP
return $classConst;
}
private function makePrivateOrWeaker(ClassConst $classConst, bool $protectedRequired): void
private function makePrivateOrWeaker(ClassConst $classConst, ?ConstantVisibility $parentConstantVisibility): void
{
if ($protectedRequired) {
if ($parentConstantVisibility !== null && $parentConstantVisibility->isProtected()) {
$this->makeProtected($classConst);
} else {
} elseif ($parentConstantVisibility !== null && $parentConstantVisibility->isPrivate() && ! $parentConstantVisibility->isProtected()) {
$this->makePrivate($classConst);
} elseif ($parentConstantVisibility === null) {
$this->makePrivate($classConst);
}
}

View File

@ -6,7 +6,6 @@ namespace Rector\SOLID\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -16,16 +15,6 @@ use Rector\Core\RectorDefinition\RectorDefinition;
*/
final class MakeUnusedClassesWithChildrenAbstractRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Classes that have no children nor are used, should have abstract', [
@ -72,12 +61,12 @@ PHP
}
// 1. is in static call?
if ($this->parsedNodesByType->findMethodCallsOnClass($className) !== []) {
if ($this->functionLikeParsedNodesFinder->findMethodCallsOnClass($className) !== []) {
return null;
}
// 2. is in new?
if ($this->parsedNodesByType->findNewNodesByClass($className) !== []) {
if ($this->parsedNodeCollector->findNewNodesByClass($className) !== []) {
return null;
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Rector\SOLID\Reflection;
use ReflectionClass;
use ReflectionClassConstant;
final class ParentConstantReflectionResolver
{
public function resolve(string $class, string $constant): ?ReflectionClassConstant
{
$reflectionClass = (new ReflectionClass($class));
$parentReflectionClass = $reflectionClass->getParentClass();
while ($parentReflectionClass !== false) {
if ($parentReflectionClass->hasConstant($constant)) {
return $parentReflectionClass->getReflectionConstant($constant);
}
$parentReflectionClass = $parentReflectionClass->getParentClass();
}
return null;
}
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Rector\SOLID\ValueObject;
final class ConstantVisibility
{
/**
* @var bool
*/
private $isPublic = false;
/**
* @var bool
*/
private $isProtected = false;
/**
* @var bool
*/
private $isPrivate = false;
public function __construct(bool $isPublic, bool $isProtected, bool $isPrivate)
{
$this->isPublic = $isPublic;
$this->isProtected = $isProtected;
$this->isPrivate = $isPrivate;
}
public function isPublic(): bool
{
return $this->isPublic;
}
public function isProtected(): bool
{
return $this->isProtected;
}
public function isPrivate(): bool
{
return $this->isPrivate;
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Rector\SOLID\Tests\Rector\ClassConst\PrivatizeLocalClassConstantRector\Fixture;
use Rector\SOLID\Tests\Rector\ClassConst\PrivatizeLocalClassConstantRector\Source\SomeProtectedParentClass;
class SkipParentClassProtected extends SomeProtectedParentClass
{
protected const SOME_CONST = 'changed_value';
}

View File

@ -18,24 +18,11 @@ final class PrivatizeLocalClassConstantRectorTest extends AbstractRectorTestCase
$this->doTestFile($file);
}
/**
* @dataProvider provideDataProtected()
*/
public function testProtected(string $file): void
{
$this->doTestFile($file);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideDataProtected(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return PrivatizeLocalClassConstantRector::class;

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\SOLID\Tests\Rector\ClassConst\PrivatizeLocalClassConstantRector\Source;
abstract class SomeProtectedParentClass
{
protected const SOME_CONST = '...';
}

View File

@ -22,7 +22,6 @@ use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -42,16 +41,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
final class FormTypeInstanceToClassConstRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
public function __construct(ParsedNodesByType $parsedNodesByType)
{
$this->parsedNodesByType = $parsedNodesByType;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
@ -180,7 +169,7 @@ PHP
$methodCall->args[$optionsPosition] = new Arg($optionsArrayNode);
}
$formTypeClassNode = $this->parsedNodesByType->findClass($className);
$formTypeClassNode = $this->classLikeParsedNodesFinder->findClass($className);
if ($formTypeClassNode === null) {
return null;
}

View File

@ -11,7 +11,6 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -24,19 +23,13 @@ use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
*/
final class AddMethodCallBasedParamTypeRector extends AbstractRector
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var TypeFactory
*/
private $typeFactory;
public function __construct(ParsedNodesByType $parsedNodesByType, TypeFactory $typeFactory)
public function __construct(TypeFactory $typeFactory)
{
$this->parsedNodesByType = $parsedNodesByType;
$this->typeFactory = $typeFactory;
}
@ -98,7 +91,7 @@ PHP
*/
public function refactor(Node $node): ?Node
{
$classMethodCalls = $this->parsedNodesByType->findClassMethodCalls($node);
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($node);
$classParameterTypes = $this->getCallTypesByPosition($classMethodCalls);

View File

@ -15,7 +15,7 @@ use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StaticType;
use PHPStan\Type\Type;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\PHPStan\Type\SelfObjectType;
@ -41,9 +41,9 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
protected $docBlockManipulator;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
protected $parsedNodesByType;
protected $parsedNodeCollector;
/**
* @var PhpParserTypeAnalyzer
@ -60,12 +60,12 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
*/
public function autowireAbstractTypeDeclarationRector(
DocBlockManipulator $docBlockManipulator,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
PhpParserTypeAnalyzer $phpParserTypeAnalyzer,
VendorLockResolver $vendorLockResolver
): void {
$this->docBlockManipulator = $docBlockManipulator;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->phpParserTypeAnalyzer = $phpParserTypeAnalyzer;
$this->vendorLockResolver = $vendorLockResolver;
}

View File

@ -18,6 +18,7 @@ use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\TypeDeclaration\Contract\TypeInferer\ReturnTypeInfererInterface;
use Rector\TypeDeclaration\TypeInferer\AbstractTypeInferer;
@ -51,7 +52,7 @@ final class YieldNodesReturnTypeInferer extends AbstractTypeInferer implements R
$types[] = new ArrayType(new MixedType(), $yieldValueStaticType);
}
if ($this->phpVersionProvider->isAtLeast('7.1')) {
if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::ITERABLE_TYPE)) {
// @see https://www.php.net/manual/en/language.types.iterable.php
$types[] = new IterableType(new MixedType(), new MixedType());
} else {

View File

@ -12,7 +12,7 @@ use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -25,23 +25,23 @@ final class VendorLockResolver
*/
private $nameResolver;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var ClassManipulator
*/
private $classManipulator;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
NameResolver $nameResolver,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
ClassManipulator $classManipulator
) {
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->classManipulator = $classManipulator;
}
@ -66,7 +66,7 @@ final class VendorLockResolver
$parentClassName = $classMethod->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== null) {
$parentClassNode = $this->parsedNodesByType->findClass($parentClassName);
$parentClassNode = $this->parsedNodeCollector->findClass($parentClassName);
if ($parentClassNode !== null) {
$parentMethodNode = $parentClassNode->getMethod($methodName);
// @todo validate type is conflicting
@ -95,7 +95,7 @@ final class VendorLockResolver
$interfaceNames = $this->classManipulator->getClassLikeNodeParentInterfaceNames($classNode);
foreach ($interfaceNames as $interfaceName) {
$interface = $this->parsedNodesByType->findInterface($interfaceName);
$interface = $this->parsedNodeCollector->findInterface($interfaceName);
// parent class method in local scope → it's ok
// @todo validate type is conflicting
if ($interface !== null && $interface->getMethod($methodName) !== null) {
@ -133,7 +133,7 @@ final class VendorLockResolver
$parentClassName = $classMethod->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== null) {
$parentClassNode = $this->parsedNodesByType->findClass($parentClassName);
$parentClassNode = $this->parsedNodeCollector->findClass($parentClassName);
if ($parentClassNode !== null) {
$parentMethodNode = $parentClassNode->getMethod($methodName);
// @todo validate type is conflicting
@ -161,7 +161,7 @@ final class VendorLockResolver
$interfaceNames = $this->classManipulator->getClassLikeNodeParentInterfaceNames($classNode);
foreach ($interfaceNames as $interfaceName) {
$interface = $this->parsedNodesByType->findInterface($interfaceName);
$interface = $this->parsedNodeCollector->findInterface($interfaceName);
// parent class method in local scope → it's ok
// @todo validate type is conflicting
if ($interface !== null && $interface->getMethod($methodName) !== null) {
@ -199,7 +199,7 @@ final class VendorLockResolver
$parentClassName = $classNode->getAttribute(AttributeKey::PARENT_CLASS_NAME);
if ($parentClassName !== null) {
$parentClassNode = $this->parsedNodesByType->findClass($parentClassName);
$parentClassNode = $this->parsedNodeCollector->findClass($parentClassName);
if ($parentClassNode !== null) {
$parentPropertyNode = $this->getProperty($parentClassNode, $propertyName);
// @todo validate type is conflicting

View File

@ -9,7 +9,7 @@ parameters:
level: max
# to allow installing with various phsptan versions without reporting old errors here
# reportUnmatchedIgnoredErrors: false
reportUnmatchedIgnoredErrors: false
autoload_directories:
- stubs
@ -225,9 +225,9 @@ parameters:
- '#Parameter \#1 \$str of function preg_quote expects string, int\|string given#'
- '#Parameter \#1 \$node of method Rector\\Core\\PhpParser\\Node\\Commander\\NodeAddingCommander\:\:wrapToExpression\(\) expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Stmt, PhpParser\\Node given#'
- '#Method Rector\\Core\\NodeContainer\\ParsedNodesByType\:\:findTrait\(\) should return PhpParser\\Node\\Stmt\\Trait_\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\NodeContainer\\ParsedNodesByType\:\:findInterface\(\) should return PhpParser\\Node\\Stmt\\Interface_\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\NodeContainer\\ParsedNodesByType\:\:findFunction\(\) should return PhpParser\\Node\\Stmt\\Function_\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\NodeContainer\\NodeCollector\\ParsedNodesByType\:\:findTrait\(\) should return PhpParser\\Node\\Stmt\\Trait_\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\NodeContainer\\NodeCollector\\ParsedNodesByType\:\:findInterface\(\) should return PhpParser\\Node\\Stmt\\Interface_\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\NodeContainer\\NodeCollector\\ParsedNodesByType\:\:findFunction\(\) should return PhpParser\\Node\\Stmt\\Function_\|null but returns PhpParser\\Node\|null#'
- '#Parameter \#2 \$propertyName of method Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\SingleMethodAssignedNodePropertyTypeInferer\:\:resolveAssignedNodeToProperty\(\) expects string, string\|null given#'
- '#Parameter \#1 \$sprintfFuncCall of method Rector\\Core\\PhpParser\\NodeTransformer\:\:transformSprintfToArray\(\) expects PhpParser\\Node\\Expr\\FuncCall, PhpParser\\Node given#'
- '#Parameter \#1 \$nodes of method Rector\\CodeQuality\\Rector\\Array_\\CallableThisArrayToAnonymousFunctionRector\:\:hasClassMethodReturn\(\) expects array<PhpParser\\Node\\Stmt\\Return_\>, array<PhpParser\\Node\> given#'
@ -235,3 +235,8 @@ parameters:
- '#PHPDoc tag @return with type iterable<object\> is not subtype of native type array#'
- '#Method Rector\\BetterPhpDocParser\\AnnotationReader\\NodeAnnotationReader\:\:createClassReflectionFromNode\(\) return type with generic class ReflectionClass does not specify its types\: T#'
- '#Method Rector\\FileSystemRector\\Rector\\AbstractFileSystemRector\:\:wrapToArg\(\) should return array<PhpParser\\Node\\Arg\> but returns array<PhpParser\\Node\\Arg\|PhpParser\\Node\\Expr\>#'
- '#Method Rector\\SOLID\\Rector\\ClassConst\\PrivatizeLocalClassConstantRector\:\:resolveParentClassConstantReflection\(\) should return ReflectionClassConstant\|null but returns ReflectionClassConstant\|false#'
- '#PHPDoc tag @var for variable \$parentClass contains generic class ReflectionClass but does not specify its types\: T#'
- '#Method Rector\\SOLID\\Reflection\\ParentConstantReflectionResolver\:\:(.*?)\(\) should return ReflectionClassConstant\|null but returns ReflectionClassConstant\|false#'
- '#Method Rector\\Core\\NodeContainer\\NodeCollector\\ParsedFunctionLikeNodesByType\:\:findFunction\(\) should return PhpParser\\Node\\Stmt\\Function_\|null but returns PhpParser\\Node\|null#'

View File

@ -53,9 +53,9 @@ services:
Rector\PhpDoc\PhpDocClassRenamer: Rector\Core\PhpDoc\PhpDocClassRenamer
Rector\Util\RectorStrings: Rector\Core\Util\RectorStrings
Rector\HttpKernel\RectorKernel: Rector\Core\HttpKernel\RectorKernel
Rector\NodeContainer\FunctionLikeParsedNodesFinder: Rector\Core\NodeContainer\FunctionLikeParsedNodesFinder
Rector\NodeContainer\FunctionLikeParsedNodesFinder: Rector\Core\NodeContainer\NodeFinder\FunctionLikeParsedNodesFinder
Rector\NodeContainer\ClassLikeParsedNodesFinder: Rector\Core\NodeContainer\ClassLikeParsedNodesFinder
Rector\NodeContainer\ParsedNodesByType: Rector\Core\NodeContainer\ParsedNodesByType
Rector\NodeContainer\ParsedNodesByType: Rector\Core\NodeContainer\NodeCollector\ParsedNodesByType
Rector\FileSystem\FileGuard: Rector\Core\FileSystem\FileGuard
Rector\FileSystem\FilesystemTweaker: Rector\Core\FileSystem\FilesystemTweaker
Rector\FileSystem\FilesFinder: Rector\Core\FileSystem\FilesFinder

View File

@ -1,77 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeContainer;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\TypeUtils;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
final class FunctionLikeParsedNodesFinder
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(
ParsedNodesByType $parsedNodesByType,
NameResolver $nameResolver,
NodeTypeResolver $nodeTypeResolver
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->nameResolver = $nameResolver;
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function findClassMethodByMethodCall(MethodCall $methodCall): ?ClassMethod
{
/** @var string|null $className */
$className = $methodCall->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return null;
}
$methodName = $this->nameResolver->getName($methodCall->name);
if ($methodName === null) {
return null;
}
return $this->parsedNodesByType->findMethod($methodName, $className);
}
public function findClassMethodByStaticCall(StaticCall $staticCall): ?ClassMethod
{
$methodName = $this->nameResolver->getName($staticCall->name);
if ($methodName === null) {
return null;
}
$objectType = $this->nodeTypeResolver->resolve($staticCall->class);
$classNames = TypeUtils::getDirectClassNames($objectType);
foreach ($classNames as $className) {
$foundMethod = $this->parsedNodesByType->findMethod($methodName, $className);
if ($foundMethod !== null) {
return $foundMethod;
}
}
return null;
}
}

View File

@ -0,0 +1,290 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeContainer\NodeCollector;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
/**
* All parsed nodes grouped type
*/
final class ParsedFunctionLikeNodeCollector
{
/**
* @var ClassMethod[][]
*/
private $methodsByType = [];
/**
* @var Function_[]
*/
private $functionsByName = [];
/**
* @var MethodCall[][][]|StaticCall[][][]
*/
private $methodsCallsByTypeAndMethod = [];
/**
* E.g. [$this, 'someLocalMethod']
* @var Array_[][][]
*/
private $arrayCallablesByTypeAndMethod = [];
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(NameResolver $nameResolver)
{
$this->nameResolver = $nameResolver;
}
/**
* To prevent circular reference
* @required
*/
public function autowireParsedNodesByType(NodeTypeResolver $nodeTypeResolver): void
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function collect(Node $node): void
{
if ($node instanceof ClassMethod) {
$this->addMethod($node);
return;
}
// array callable - [$this, 'someCall']
if ($node instanceof Array_) {
$arrayCallableClassAndMethod = $this->matchArrayCallableClassAndMethod($node);
if ($arrayCallableClassAndMethod === null) {
return;
}
[$className, $methodName] = $arrayCallableClassAndMethod;
if (! method_exists($className, $methodName)) {
return;
}
$this->arrayCallablesByTypeAndMethod[$className][$methodName][] = $node;
return;
}
if ($node instanceof MethodCall || $node instanceof StaticCall) {
$this->addCall($node);
}
if ($node instanceof Function_) {
$functionName = $this->nameResolver->getName($node);
if ($functionName === null) {
return;
}
$this->functionsByName[$functionName] = $node;
}
}
public function findFunction(string $name): ?Function_
{
return $this->functionsByName[$name] ?? null;
}
/**
* @return MethodCall[][]|StaticCall[][]
*/
public function findMethodCallsOnClass(string $className): array
{
return $this->methodsCallsByTypeAndMethod[$className] ?? [];
}
/**
* @return MethodCall[]|StaticCall[]|Array_[]
*/
public function findByClassAndMethod(string $className, string $methodName): array
{
return $this->methodsCallsByTypeAndMethod[$className][$methodName] ?? $this->arrayCallablesByTypeAndMethod[$className][$methodName] ?? [];
}
public function findMethod(string $className, string $methodName): ?ClassMethod
{
if (isset($this->methodsByType[$className][$methodName])) {
return $this->methodsByType[$className][$methodName];
}
$parentClass = $className;
while ($parentClass = get_parent_class($parentClass)) {
if (isset($this->methodsByType[$parentClass][$methodName])) {
return $this->methodsByType[$parentClass][$methodName];
}
}
return null;
}
private function addMethod(ClassMethod $classMethod): void
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) { // anonymous
return;
}
$methodName = $this->nameResolver->getName($classMethod);
$this->methodsByType[$className][$methodName] = $classMethod;
}
/**
* @todo decouple to NodeAnalyzer
* Matches array like: "[$this, 'methodName']" ['ClassName', 'methodName']
* @return string[]|null
*/
private function matchArrayCallableClassAndMethod(Array_ $array): ?array
{
if (count($array->items) !== 2) {
return null;
}
if ($array->items[0] === null) {
return null;
}
// $this, self, static, FQN
if (! $this->isThisVariable($array->items[0]->value)) {
return null;
}
if ($array->items[1] === null) {
return null;
}
if (! $array->items[1]->value instanceof String_) {
return null;
}
/** @var String_ $string */
$string = $array->items[1]->value;
$methodName = $string->value;
$className = $array->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return null;
}
return [$className, $methodName];
}
/**
* @param MethodCall|StaticCall $node
*/
private function addCall(Node $node): void
{
// one node can be of multiple-class types
if ($node instanceof MethodCall) {
if ($node->var instanceof MethodCall) {
$classType = $this->resolveNodeClassTypes($node);
} else {
$classType = $this->resolveNodeClassTypes($node->var);
}
} else {
$classType = $this->resolveNodeClassTypes($node->class);
}
$methodName = $this->nameResolver->getName($node);
if ($classType instanceof MixedType) { // anonymous
return;
}
if ($methodName === null) {
return;
}
if ($classType instanceof ObjectType) {
$this->methodsCallsByTypeAndMethod[$classType->getClassName()][$methodName][] = $node;
}
if ($classType instanceof UnionType) {
foreach ($classType->getTypes() as $unionedType) {
if (! $unionedType instanceof ObjectType) {
continue;
}
$this->methodsCallsByTypeAndMethod[$unionedType->getClassName()][$methodName][] = $node;
}
}
}
private function isThisVariable(Node $node): bool
{
// $this
if ($node instanceof Variable && $this->nameResolver->isName($node, 'this')) {
return true;
}
if ($node instanceof ClassConstFetch) {
if (! $this->nameResolver->isName($node->name, 'class')) {
return false;
}
// self::class, static::class
if ($this->nameResolver->isNames($node->class, ['self', 'static'])) {
return true;
}
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return false;
}
return $this->nameResolver->isName($node->class, $className);
}
return false;
}
private function resolveNodeClassTypes(Node $node): Type
{
if ($node instanceof MethodCall && $node->var instanceof Variable && $node->var->name === 'this') {
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
if ($className) {
return new ObjectType($className);
}
return new MixedType();
}
if ($node instanceof MethodCall) {
return $this->nodeTypeResolver->resolve($node->var);
}
return $this->nodeTypeResolver->resolve($node);
}
}

View File

@ -0,0 +1,287 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeContainer\NodeCollector;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Param;
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\NotImplementedException;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* All parsed nodes grouped type
*/
final class ParsedNodeCollector
{
/**
* @var string[]
*/
private $collectableNodeTypes = [
Class_::class,
Interface_::class,
ClassConst::class,
ClassConstFetch::class,
Trait_::class,
ClassMethod::class,
// simply collected
New_::class,
StaticCall::class,
MethodCall::class,
// for array callable - [$this, 'someCall']
Array_::class,
// for unused classes
Param::class,
];
/**
* @var Class_[]
*/
private $classes = [];
/**
* @var ClassConst[][]
*/
private $constantsByType = [];
/**
* @var Node[][]
*/
private $simpleParsedNodesByType = [];
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var Interface_[]
*/
private $interfaces = [];
/**
* @var Trait_[]
*/
private $traits = [];
public function __construct(NameResolver $nameResolver)
{
$this->nameResolver = $nameResolver;
}
/**
* @template T of object
* @param class-string<T> $type
* @return Node[]|iterable<T>
*/
public function getNodesByType(string $type): array
{
return $this->simpleParsedNodesByType[$type] ?? [];
}
/**
* @return Interface_[]
*/
public function getInterfaces(): array
{
return $this->interfaces;
}
/**
* @return Class_[]
*/
public function getClasses(): array
{
return $this->classes;
}
public function findClass(string $name): ?Class_
{
return $this->classes[$name] ?? null;
}
public function findInterface(string $name): ?Interface_
{
return $this->interfaces[$name] ?? null;
}
public function findTrait(string $name): ?Trait_
{
return $this->traits[$name] ?? null;
}
/**
* Guessing the nearest neighboor.
* Used e.g. for "XController"
*/
public function findByShortName(string $shortName): ?Class_
{
foreach ($this->classes as $className => $classNode) {
if (Strings::endsWith($className, '\\' . $shortName)) {
return $classNode;
}
}
return null;
}
/**
* @return Class_|Interface_|null
*/
public function findClassOrInterface(string $type): ?ClassLike
{
$class = $this->findClass($type);
if ($class !== null) {
return $class;
}
return $this->findInterface($type);
}
public function findClassConstant(string $className, string $constantName): ?ClassConst
{
if (Strings::contains($constantName, '\\')) {
throw new ShouldNotHappenException(sprintf('Switched arguments in "%s"', __METHOD__));
}
return $this->constantsByType[$className][$constantName] ?? null;
}
public function isCollectableNode(Node $node): bool
{
foreach ($this->collectableNodeTypes as $collectableNodeType) {
if (is_a($node, $collectableNodeType, true)) {
return true;
}
}
return false;
}
public function collect(Node $node): void
{
$nodeClass = get_class($node);
if ($node instanceof Class_) {
$this->addClass($node);
return;
}
if ($node instanceof Interface_ || $node instanceof Trait_) {
$name = $this->nameResolver->getName($node);
if ($name === null) {
throw new ShouldNotHappenException();
}
if ($node instanceof Interface_) {
$this->interfaces[$name] = $node;
} elseif ($node instanceof Trait_) {
$this->traits[$name] = $node;
}
return;
}
if ($node instanceof ClassConst) {
$this->addClassConstant($node);
return;
}
// simple collect
$this->simpleParsedNodesByType[$nodeClass][] = $node;
}
/**
* @return New_[]
*/
public function findNewNodesByClass(string $className): array
{
$newNodesByClass = [];
/** @var New_[] $news */
$news = $this->getNodesByType(New_::class);
foreach ($news as $new) {
if (! $this->nameResolver->isName($new->class, $className)) {
continue;
}
$newNodesByClass[] = $new;
}
return $newNodesByClass;
}
public function findClassConstantByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
{
$class = $this->nameResolver->getName($classConstFetch->class);
if ($class === 'self') {
/** @var string|null $class */
$class = $classConstFetch->getAttribute(AttributeKey::CLASS_NAME);
} elseif ($class === 'parent') {
/** @var string|null $class */
$class = $classConstFetch->getAttribute(AttributeKey::PARENT_CLASS_NAME);
}
if ($class === null) {
throw new NotImplementedException();
}
/** @var string $constantName */
$constantName = $this->nameResolver->getName($classConstFetch->name);
return $this->findClassConstant($class, $constantName);
}
private function addClass(Class_ $classNode): void
{
if ($this->isClassAnonymous($classNode)) {
return;
}
$className = $classNode->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
throw new ShouldNotHappenException();
}
$this->classes[$className] = $classNode;
}
private function addClassConstant(ClassConst $classConst): void
{
$className = $classConst->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
// anonymous class constant
return;
}
$constantName = $this->nameResolver->getName($classConst);
$this->constantsByType[$className][$constantName] = $classConst;
}
private function isClassAnonymous(Class_ $classNode): bool
{
if ($classNode->isAnonymous() || $classNode->name === null) {
return true;
}
// PHPStan polution
return Strings::startsWith($classNode->name->toString(), 'AnonymousClass');
}
}

View File

@ -2,31 +2,32 @@
declare(strict_types=1);
namespace Rector\Core\NodeContainer;
namespace Rector\Core\NodeContainer\NodeFinder;
use Nette\Utils\Strings;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class ClassLikeParsedNodesFinder
{
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
/**
* @var NameResolver
*/
private $nameResolver;
public function __construct(ParsedNodesByType $parsedNodesByType, NameResolver $nameResolver)
public function __construct(ParsedNodeCollector $parsedNodeCollector, NameResolver $nameResolver)
{
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->nameResolver = $nameResolver;
}
@ -37,7 +38,7 @@ final class ClassLikeParsedNodesFinder
{
$childrenClasses = [];
foreach ($this->parsedNodesByType->getClasses() as $classNode) {
foreach ($this->parsedNodeCollector->getClasses() as $classNode) {
$currentClassName = $classNode->getAttribute(AttributeKey::CLASS_NAME);
if (! $this->isChildOrEqualClassLike($class, $currentClassName)) {
continue;
@ -56,7 +57,7 @@ final class ClassLikeParsedNodesFinder
{
$classNodes = [];
foreach ($this->parsedNodesByType->getClasses() as $className => $classNode) {
foreach ($this->parsedNodeCollector->getClasses() as $className => $classNode) {
if (! Strings::endsWith($className, $suffix)) {
continue;
}
@ -86,7 +87,7 @@ final class ClassLikeParsedNodesFinder
continue;
}
$foundTrait = $this->parsedNodesByType->findTrait($traitName);
$foundTrait = $this->parsedNodeCollector->findTrait($traitName);
if ($foundTrait !== null) {
$traits[] = $foundTrait;
}
@ -111,7 +112,7 @@ final class ClassLikeParsedNodesFinder
{
$implementerInterfaces = [];
foreach ($this->parsedNodesByType->getInterfaces() as $interfaceNode) {
foreach ($this->parsedNodeCollector->getInterfaces() as $interfaceNode) {
$className = $interfaceNode->getAttribute(AttributeKey::CLASS_NAME);
if (! $this->isChildOrEqualClassLike($interface, $className)) {
@ -124,6 +125,16 @@ final class ClassLikeParsedNodesFinder
return $implementerInterfaces;
}
public function findInterface(string $class): ?Interface_
{
return $this->parsedNodeCollector->findInterface($class);
}
public function findClass(string $name): ?Class_
{
return $this->parsedNodeCollector->findClass($name);
}
private function isChildOrEqualClassLike(string $desiredClass, ?string $currentClassName): bool
{
if ($currentClassName === null) {

View File

@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeContainer\NodeFinder;
use Nette\Utils\Strings;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\TypeUtils;
use Rector\Core\NodeContainer\NodeCollector\ParsedFunctionLikeNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use ReflectionClass;
final class FunctionLikeParsedNodesFinder
{
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var ParsedFunctionLikeNodeCollector
*/
private $parsedFunctionLikeNodeCollector;
public function __construct(
NameResolver $nameResolver,
NodeTypeResolver $nodeTypeResolver,
ParsedFunctionLikeNodeCollector $parsedFunctionLikeNodeCollector
) {
$this->nameResolver = $nameResolver;
$this->nodeTypeResolver = $nodeTypeResolver;
$this->parsedFunctionLikeNodeCollector = $parsedFunctionLikeNodeCollector;
}
public function findClassMethodByMethodCall(MethodCall $methodCall): ?ClassMethod
{
/** @var string|null $className */
$className = $methodCall->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return null;
}
$methodName = $this->nameResolver->getName($methodCall->name);
if ($methodName === null) {
return null;
}
return $this->findMethod($methodName, $className);
}
public function findClassMethodByStaticCall(StaticCall $staticCall): ?ClassMethod
{
$methodName = $this->nameResolver->getName($staticCall->name);
if ($methodName === null) {
return null;
}
$objectType = $this->nodeTypeResolver->resolve($staticCall->class);
$classNames = TypeUtils::getDirectClassNames($objectType);
foreach ($classNames as $className) {
$foundMethod = $this->findMethod($methodName, $className);
if ($foundMethod !== null) {
return $foundMethod;
}
}
return null;
}
public function findFunction(string $name): ?Function_
{
return $this->parsedFunctionLikeNodeCollector->findFunction($name);
}
public function findMethod(string $methodName, string $className): ?ClassMethod
{
return $this->parsedFunctionLikeNodeCollector->findMethod($className, $methodName);
}
/**
* @todo deocpule
*/
public function isStaticMethod(string $methodName, string $className): bool
{
$methodNode = $this->findMethod($methodName, $className);
if ($methodNode !== null) {
return $methodNode->isStatic();
}
// could be static in doc type magic
// @see https://regex101.com/r/tlvfTB/1
if (class_exists($className) || trait_exists($className)) {
$reflectionClass = new ReflectionClass($className);
if (Strings::match(
(string) $reflectionClass->getDocComment(),
'#@method\s*static\s*(.*?)\b' . $methodName . '\b#'
)) {
return true;
}
// probably magic method → we don't know
if (! method_exists($className, $methodName)) {
return false;
}
$methodReflection = $reflectionClass->getMethod($methodName);
return $methodReflection->isStatic();
}
return false;
}
/**
* @return MethodCall[]|StaticCall[]|Array_[]
*/
public function findClassMethodCalls(ClassMethod $classMethod): array
{
/** @var string|null $className */
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) { // anonymous
return [];
}
/** @var string|null $methodName */
$methodName = $this->nameResolver->getName($classMethod);
if ($methodName === null) {
return [];
}
return $this->parsedFunctionLikeNodeCollector->findByClassAndMethod($className, $methodName);
}
/**
* @return MethodCall[][]|StaticCall[][]
*/
public function findMethodCallsOnClass(string $className): array
{
return $this->parsedFunctionLikeNodeCollector->findMethodCallsOnClass($className);
}
}

View File

@ -1,555 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeContainer;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Trait_;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\Core\Exception\NotImplementedException;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use ReflectionClass;
/**
* All parsed nodes grouped type
*/
final class ParsedNodesByType
{
/**
* @var string[]
*/
private $collectableNodeTypes = [
Class_::class,
Interface_::class,
ClassConst::class,
ClassConstFetch::class,
Trait_::class,
ClassMethod::class,
Function_::class,
// simply collected
New_::class,
StaticCall::class,
MethodCall::class,
// for array callable - [$this, 'someCall']
Array_::class,
// for unused classes
Param::class,
];
/**
* @var Class_[]
*/
private $classes = [];
/**
* @var ClassConst[][]
*/
private $constantsByType = [];
/**
* @var ClassMethod[][]
*/
private $methodsByType = [];
/**
* @var Node[][]
*/
private $simpleParsedNodesByType = [];
/**
* @var MethodCall[][][]|StaticCall[][][]
*/
private $methodsCallsByTypeAndMethod = [];
/**
* E.g. [$this, 'someLocalMethod']
* @var Array_[][][]
*/
private $arrayCallablesByTypeAndMethod = [];
/**
* @var NameResolver
*/
private $nameResolver;
/**
* @var NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(NameResolver $nameResolver)
{
$this->nameResolver = $nameResolver;
}
/**
* @template T of object
* @param class-string<T> $type
* @return Node[]|iterable<T>
*/
public function getNodesByType(string $type): array
{
return $this->simpleParsedNodesByType[$type] ?? [];
}
/**
* @return Interface_[]
*/
public function getInterfaces(): array
{
return $this->simpleParsedNodesByType[Interface_::class] ?? [];
}
/**
* @return Class_[]
*/
public function getClasses(): array
{
return $this->classes;
}
/**
* To prevent circular reference
* @required
*/
public function autowireParsedNodesByType(NodeTypeResolver $nodeTypeResolver): void
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function findClass(string $name): ?Class_
{
return $this->classes[$name] ?? null;
}
public function findInterface(string $name): ?Interface_
{
return $this->simpleParsedNodesByType[Interface_::class][$name] ?? null;
}
public function findTrait(string $name): ?Trait_
{
return $this->simpleParsedNodesByType[Trait_::class][$name] ?? null;
}
/**
* Guessing the nearest neighboor.
* Used e.g. for "XController"
*/
public function findByShortName(string $shortName): ?Class_
{
foreach ($this->classes as $className => $classNode) {
if (Strings::endsWith($className, '\\' . $shortName)) {
return $classNode;
}
}
return null;
}
/**
* @return Class_|Interface_|null
*/
public function findClassOrInterface(string $type): ?ClassLike
{
$class = $this->findClass($type);
if ($class !== null) {
return $class;
}
return $this->findInterface($type);
}
public function findClassConstant(string $className, string $constantName): ?ClassConst
{
if (Strings::contains($constantName, '\\')) {
throw new ShouldNotHappenException(sprintf('Switched arguments in "%s"', __METHOD__));
}
return $this->constantsByType[$className][$constantName] ?? null;
}
public function findFunction(string $name): ?Function_
{
return $this->simpleParsedNodesByType[Function_::class][$name] ?? null;
}
public function findMethod(string $methodName, string $className): ?ClassMethod
{
if (isset($this->methodsByType[$className][$methodName])) {
return $this->methodsByType[$className][$methodName];
}
$parentClass = $className;
while ($parentClass = get_parent_class($parentClass)) {
if (isset($this->methodsByType[$parentClass][$methodName])) {
return $this->methodsByType[$parentClass][$methodName];
}
}
return null;
}
public function isStaticMethod(string $methodName, string $className): bool
{
$methodNode = $this->findMethod($methodName, $className);
if ($methodNode !== null) {
return $methodNode->isStatic();
}
// could be static in doc type magic
// @see https://regex101.com/r/tlvfTB/1
if (class_exists($className) || trait_exists($className)) {
$reflectionClass = new ReflectionClass($className);
if (Strings::match(
(string) $reflectionClass->getDocComment(),
'#@method\s*static\s*(.*?)\b' . $methodName . '\b#'
)) {
return true;
}
// probably magic method → we don't know
if (! method_exists($className, $methodName)) {
return false;
}
$methodReflection = $reflectionClass->getMethod($methodName);
return $methodReflection->isStatic();
}
return false;
}
public function isCollectableNode(Node $node): bool
{
foreach ($this->collectableNodeTypes as $collectableNodeType) {
if (is_a($node, $collectableNodeType, true)) {
return true;
}
}
return false;
}
public function collect(Node $node): void
{
$nodeClass = get_class($node);
if ($node instanceof Class_) {
$this->addClass($node);
return;
}
if ($node instanceof Interface_ || $node instanceof Trait_ || $node instanceof Function_) {
$name = $this->nameResolver->getName($node);
if ($name === null) {
throw new ShouldNotHappenException();
}
$this->simpleParsedNodesByType[$nodeClass][$name] = $node;
return;
}
if ($node instanceof ClassConst) {
$this->addClassConstant($node);
return;
}
if ($node instanceof ClassMethod) {
$this->addMethod($node);
return;
}
// array callable - [$this, 'someCall']
if ($node instanceof Array_) {
$arrayCallableClassAndMethod = $this->matchArrayCallableClassAndMethod($node);
if ($arrayCallableClassAndMethod === null) {
return;
}
[$className, $methodName] = $arrayCallableClassAndMethod;
if (! method_exists($className, $methodName)) {
return;
}
$this->arrayCallablesByTypeAndMethod[$className][$methodName][] = $node;
return;
}
if ($node instanceof MethodCall || $node instanceof StaticCall) {
$this->addCall($node);
}
// simple collect
$this->simpleParsedNodesByType[$nodeClass][] = $node;
}
/**
* @return MethodCall[]|StaticCall[]|Array_[]
*/
public function findClassMethodCalls(ClassMethod $classMethod): array
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) { // anonymous
return [];
}
$methodName = $this->nameResolver->getName($classMethod);
if ($methodName === null) {
return [];
}
return $this->methodsCallsByTypeAndMethod[$className][$methodName] ?? $this->arrayCallablesByTypeAndMethod[$className][$methodName] ?? [];
}
/**
* @return MethodCall[][]|StaticCall[][]
*/
public function findMethodCallsOnClass(string $className): array
{
return $this->methodsCallsByTypeAndMethod[$className] ?? [];
}
/**
* @return New_[]
*/
public function findNewNodesByClass(string $className): array
{
$newNodesByClass = [];
/** @var New_[] $news */
$news = $this->getNodesByType(New_::class);
foreach ($news as $new) {
if (! $this->nameResolver->isName($new->class, $className)) {
continue;
}
$newNodesByClass[] = $new;
}
return $newNodesByClass;
}
public function findClassConstantByClassConstFetch(ClassConstFetch $classConstFetch): ?ClassConst
{
$class = $this->nameResolver->getName($classConstFetch->class);
if ($class === 'self') {
/** @var string|null $class */
$class = $classConstFetch->getAttribute(AttributeKey::CLASS_NAME);
} elseif ($class === 'parent') {
/** @var string|null $class */
$class = $classConstFetch->getAttribute(AttributeKey::PARENT_CLASS_NAME);
}
if ($class === null) {
throw new NotImplementedException();
}
/** @var string $constantName */
$constantName = $this->nameResolver->getName($classConstFetch->name);
return $this->findClassConstant($class, $constantName);
}
private function addClass(Class_ $classNode): void
{
if ($this->isClassAnonymous($classNode)) {
return;
}
$className = $classNode->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
throw new ShouldNotHappenException();
}
$this->classes[$className] = $classNode;
}
private function addClassConstant(ClassConst $classConst): void
{
$className = $classConst->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
// anonymous class constant
return;
}
$constantName = $this->nameResolver->getName($classConst);
$this->constantsByType[$className][$constantName] = $classConst;
}
private function addMethod(ClassMethod $classMethod): void
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) { // anonymous
return;
}
$methodName = $this->nameResolver->getName($classMethod);
$this->methodsByType[$className][$methodName] = $classMethod;
}
/**
* Matches array like: "[$this, 'methodName']" ['ClassName', 'methodName']
* @return string[]|null
*/
private function matchArrayCallableClassAndMethod(Array_ $array): ?array
{
if (count($array->items) !== 2) {
return null;
}
if ($array->items[0] === null) {
return null;
}
// $this, self, static, FQN
if (! $this->isThisVariable($array->items[0]->value)) {
return null;
}
if ($array->items[1] === null) {
return null;
}
if (! $array->items[1]->value instanceof String_) {
return null;
}
/** @var String_ $string */
$string = $array->items[1]->value;
$methodName = $string->value;
$className = $array->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return null;
}
return [$className, $methodName];
}
/**
* @param MethodCall|StaticCall $node
*/
private function addCall(Node $node): void
{
// one node can be of multiple-class types
if ($node instanceof MethodCall) {
if ($node->var instanceof MethodCall) {
$classType = $this->resolveNodeClassTypes($node);
} else {
$classType = $this->resolveNodeClassTypes($node->var);
}
} else {
$classType = $this->resolveNodeClassTypes($node->class);
}
$methodName = $this->nameResolver->getName($node);
if ($classType instanceof MixedType) { // anonymous
return;
}
if ($methodName === null) {
return;
}
if ($classType instanceof ObjectType) {
$this->methodsCallsByTypeAndMethod[$classType->getClassName()][$methodName][] = $node;
}
if ($classType instanceof UnionType) {
foreach ($classType->getTypes() as $unionedType) {
if (! $unionedType instanceof ObjectType) {
continue;
}
$this->methodsCallsByTypeAndMethod[$unionedType->getClassName()][$methodName][] = $node;
}
}
}
private function isClassAnonymous(Class_ $classNode): bool
{
if ($classNode->isAnonymous() || $classNode->name === null) {
return true;
}
// PHPStan polution
return Strings::startsWith($classNode->name->toString(), 'AnonymousClass');
}
private function isThisVariable(Node $node): bool
{
// $this
if ($node instanceof Variable && $this->nameResolver->isName($node, 'this')) {
return true;
}
if ($node instanceof ClassConstFetch) {
if (! $this->nameResolver->isName($node->name, 'class')) {
return false;
}
// self::class, static::class
if ($this->nameResolver->isNames($node->class, ['self', 'static'])) {
return true;
}
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
if ($className === null) {
return false;
}
return $this->nameResolver->isName($node->class, $className);
}
return false;
}
private function resolveNodeClassTypes(Node $node): Type
{
if ($node instanceof MethodCall && $node->var instanceof Variable && $node->var->name === 'this') {
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
if ($className) {
return new ObjectType($className);
}
return new MixedType();
}
if ($node instanceof MethodCall) {
return $this->nodeTypeResolver->resolve($node->var);
}
return $this->nodeTypeResolver->resolve($node);
}
}

View File

@ -13,7 +13,7 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Scalar\String_;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
@ -57,11 +57,6 @@ final class RegexPatternArgumentManipulator
*/
private $nameResolver;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var BetterNodeFinder
*/
@ -72,16 +67,21 @@ final class RegexPatternArgumentManipulator
*/
private $betterStandardPrinter;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
NodeTypeResolver $nodeTypeResolver,
NameResolver $nameResolver,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
BetterNodeFinder $betterNodeFinder,
BetterStandardPrinter $betterStandardPrinter
) {
$this->nodeTypeResolver = $nodeTypeResolver;
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->betterNodeFinder = $betterNodeFinder;
$this->betterStandardPrinter = $betterStandardPrinter;
}
@ -204,7 +204,7 @@ final class RegexPatternArgumentManipulator
*/
private function resolveClassConstFetchValue(ClassConstFetch $classConstFetch): array
{
$classConstNode = $this->parsedNodesByType->findClassConstantByClassConstFetch($classConstFetch);
$classConstNode = $this->parsedNodeCollector->findClassConstantByClassConstFetch($classConstFetch);
if ($classConstNode === null) {
return [];
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Core\Php;
use Nette\Utils\Strings;
use Rector\Core\ValueObject\PhpVersionFeature;
final class TypeAnalyzer
{
@ -30,7 +31,7 @@ final class TypeAnalyzer
public function __construct(PhpVersionProvider $phpVersionProvider)
{
if ($phpVersionProvider->isAtLeast('7.2')) {
if ($phpVersionProvider->isAtLeast(PhpVersionFeature::OBJECT_TYPE)) {
$this->phpSupportedTypes[] = 'object';
}
}
@ -78,9 +79,4 @@ final class TypeAnalyzer
return $type;
}
public function isPhpSupported(string $type): bool
{
return in_array($type, $this->phpSupportedTypes, true);
}
}

View File

@ -7,19 +7,14 @@ namespace Rector\Core\PhpParser\Node\Manipulator;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\NodeContainer\ClassLikeParsedNodesFinder;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\NodeContainer\NodeFinder\ClassLikeParsedNodesFinder;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class ChildAndParentClassManipulator
{
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @var NodeFactory
*/
@ -35,16 +30,21 @@ final class ChildAndParentClassManipulator
*/
private $classLikeParsedNodesFinder;
/**
* @var ParsedNodeCollector
*/
private $parsedNodeCollector;
public function __construct(
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
NodeFactory $nodeFactory,
NameResolver $nameResolver,
ClassLikeParsedNodesFinder $classLikeParsedNodesFinder
) {
$this->parsedNodesByType = $parsedNodesByType;
$this->nodeFactory = $nodeFactory;
$this->nameResolver = $nameResolver;
$this->classLikeParsedNodesFinder = $classLikeParsedNodesFinder;
$this->parsedNodeCollector = $parsedNodeCollector;
}
/**
@ -59,7 +59,7 @@ final class ChildAndParentClassManipulator
}
// not in analyzed scope, nothing we can do
$parentClassNode = $this->parsedNodesByType->findClass($parentClassName);
$parentClassNode = $this->parsedNodeCollector->findClass($parentClassName);
if ($parentClassNode !== null) {
$this->completeParentConstructorBasedOnParentNode($parentClassNode, $classMethod);
return;
@ -142,7 +142,7 @@ final class ChildAndParentClassManipulator
return null;
}
$classNode = $this->parsedNodesByType->findClass($parentClassName);
$classNode = $this->parsedNodeCollector->findClass($parentClassName);
}
return null;

View File

@ -8,7 +8,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
@ -32,9 +32,9 @@ final class ClassConstManipulator
private $betterStandardPrinter;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
/**
* @var ClassManipulator
@ -45,13 +45,13 @@ final class ClassConstManipulator
NameResolver $nameResolver,
BetterNodeFinder $betterNodeFinder,
BetterStandardPrinter $betterStandardPrinter,
ParsedNodesByType $parsedNodesByType,
ParsedNodeCollector $parsedNodeCollector,
ClassManipulator $classManipulator
) {
$this->nameResolver = $nameResolver;
$this->betterNodeFinder = $betterNodeFinder;
$this->betterStandardPrinter = $betterStandardPrinter;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->classManipulator = $classManipulator;
}
@ -68,7 +68,7 @@ final class ClassConstManipulator
$searchInNodes = [$classNode];
foreach ($this->classManipulator->getUsedTraits($classNode) as $trait) {
$trait = $this->parsedNodesByType->findTrait((string) $trait);
$trait = $this->parsedNodeCollector->findTrait((string) $trait);
if ($trait === null) {
continue;
}

View File

@ -15,7 +15,7 @@ use PhpParser\Node\Stmt\PropertyProperty;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocNode\JMS\SerializerTypeTagValueNode;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ClassLikeParsedNodesFinder;
use Rector\Core\NodeContainer\NodeFinder\ClassLikeParsedNodesFinder;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;

View File

@ -14,7 +14,7 @@ use PhpParser\Node\Scalar\MagicConst\File;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\ConstantScalarType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\PhpParser\Node\Resolver\NameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
@ -36,9 +36,9 @@ final class ValueResolver
private $constExprEvaluator;
/**
* @var ParsedNodesByType
* @var ParsedNodeCollector
*/
private $parsedNodesByType;
private $parsedNodeCollector;
/**
* @var NodeTypeResolver
@ -48,10 +48,10 @@ final class ValueResolver
public function __construct(
NameResolver $nameResolver,
NodeTypeResolver $nodeTypeResolver,
ParsedNodesByType $parsedNodesByType
ParsedNodeCollector $parsedNodeCollector
) {
$this->nameResolver = $nameResolver;
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->nodeTypeResolver = $nodeTypeResolver;
}
@ -192,7 +192,7 @@ final class ValueResolver
return $class;
}
$classConstNode = $this->parsedNodesByType->findClassConstant($class, $constant);
$classConstNode = $this->parsedNodeCollector->findClassConstant($class, $constant);
if ($classConstNode === null) {
// fallback to the name

View File

@ -15,15 +15,12 @@ use PhpParser\Node\Stmt\Expression;
use PhpParser\NodeVisitorAbstract;
use PHPStan\Analyser\Scope;
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
use Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector;
use Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector;
use Rector\Core\Commander\CommanderCollector;
use Rector\Core\Contract\PhpParser\Node\CommanderInterface;
use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\DeadCode\Rector\FunctionLike\RemoveCodeAfterReturnRector;
use Rector\Core\Exclusion\ExclusionManager;
use Rector\Core\NodeContainer\ClassLikeParsedNodesFinder;
use Rector\Core\NodeContainer\FunctionLikeParsedNodesFinder;
use Rector\Core\NodeContainer\NodeFinder\ClassLikeParsedNodesFinder;
use Rector\Core\NodeContainer\NodeFinder\FunctionLikeParsedNodesFinder;
use Rector\NodeTypeResolver\FileSystem\CurrentFileInfoProvider;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
@ -83,15 +80,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
*/
protected $staticTypeMapper;
/**
* @var ClassLikeParsedNodesFinder
*/
protected $classLikeParsedNodesFinder;
/**
* @var FunctionLikeParsedNodesFinder
*/
protected $functionLikeParsedNodesFinder;
/**
* Run once in the every end of one processed file
*/
@ -111,9 +99,7 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
CurrentFileInfoProvider $currentFileInfoProvider,
PhpDocInfoPrinter $phpDocInfoPrinter,
DocBlockManipulator $docBlockManipulator,
StaticTypeMapper $staticTypeMapper,
ClassLikeParsedNodesFinder $classLikeParsedNodesFinder,
FunctionLikeParsedNodesFinder $functionLikeParsedNodesFinder
StaticTypeMapper $staticTypeMapper
): void {
$this->symfonyStyle = $symfonyStyle;
$this->phpVersionProvider = $phpVersionProvider;
@ -124,8 +110,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
$this->phpDocInfoPrinter = $phpDocInfoPrinter;
$this->docBlockManipulator = $docBlockManipulator;
$this->staticTypeMapper = $staticTypeMapper;
$this->classLikeParsedNodesFinder = $classLikeParsedNodesFinder;
$this->functionLikeParsedNodesFinder = $functionLikeParsedNodesFinder;
}
/**

View File

@ -23,6 +23,7 @@ trait AbstractRectorTrait
use ValueResolverTrait;
use CallableNodeTraverserTrait;
use ComplexRemovalTrait;
use NodeCollectorTrait;
protected function isNonAnonymousClass(?Node $node): bool
{

View File

@ -40,7 +40,8 @@ use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeContainer\ParsedNodesByType;
use Rector\Core\NodeContainer\NodeCollector\ParsedNodeCollector;
use Rector\Core\NodeContainer\NodeFinder\FunctionLikeParsedNodesFinder;
use Rector\Core\PhpParser\Node\Commander\NodeRemovingCommander;
use Rector\Core\PhpParser\Node\Manipulator\PropertyManipulator;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -50,25 +51,27 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
*/
trait ComplexRemovalTrait
{
/**
* @var ParsedNodeCollector
*/
protected $parsedNodeCollector;
/**
* @var PropertyManipulator
*/
private $propertyManipulator;
/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;
/**
* @required
*/
public function autowireComplextRemovalTrait(
PropertyManipulator $propertyManipulator,
ParsedNodesByType $parsedNodesByType
ParsedNodeCollector $parsedNodeCollector,
FunctionLikeParsedNodesFinder $functionLikeParsedNodesFinder
): void {
$this->parsedNodesByType = $parsedNodesByType;
$this->parsedNodeCollector = $parsedNodeCollector;
$this->propertyManipulator = $propertyManipulator;
$this->functionLikeParsedNodesFinder = $functionLikeParsedNodesFinder;
}
abstract protected function removeNode(Node $node): void;
@ -77,7 +80,7 @@ trait ComplexRemovalTrait
{
$this->removeNode($classMethod);
$classMethodCalls = $this->parsedNodesByType->findClassMethodCalls($classMethod);
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($classMethod);
foreach ($classMethodCalls as $classMethodCall) {
if ($classMethodCall instanceof Array_) {
continue;

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Rector\AbstractRector;
use Rector\Core\NodeContainer\NodeFinder\ClassLikeParsedNodesFinder;
use Rector\Core\NodeContainer\NodeFinder\FunctionLikeParsedNodesFinder;
/**
* This could be part of @see AbstractRector, but decopuling to trait
* makes clear what code has 1 purpose.
*/
trait NodeCollectorTrait
{
/**
* @var ClassLikeParsedNodesFinder
*/
protected $classLikeParsedNodesFinder;
/**
* @var FunctionLikeParsedNodesFinder
*/
protected $functionLikeParsedNodesFinder;
/**
* @required
*/
public function autowireNodeCollectorTrait(
ClassLikeParsedNodesFinder $classLikeParsedNodesFinder,
FunctionLikeParsedNodesFinder $functionLikeParsedNodesFinder
): void {
$this->classLikeParsedNodesFinder = $classLikeParsedNodesFinder;
$this->functionLikeParsedNodesFinder = $functionLikeParsedNodesFinder;
}
}