%PDF- %PDF-
Direktori : /home/vacivi36/vacivitta_bakcup/vendor/rector/rector/src/NodeManipulator/ |
Current File : /home/vacivi36/vacivitta_bakcup/vendor/rector/rector/src/NodeManipulator/PropertyManipulator.php |
<?php declare (strict_types=1); namespace Rector\Core\NodeManipulator; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\PostDec; use PhpParser\Node\Expr\PostInc; use PhpParser\Node\Expr\PreDec; use PhpParser\Node\Expr\PreInc; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Property; use PHPStan\Reflection\ParametersAcceptorSelector; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\Core\PhpParser\Node\BetterNodeFinder; use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder; use Rector\Core\Reflection\ReflectionResolver; use Rector\Core\ValueObject\MethodName; use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; use Rector\ReadWrite\Guard\VariableToConstantGuard; use Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer; use RectorPrefix20211231\Symplify\PackageBuilder\Php\TypeChecker; /** * For inspiration to improve this service, * @see examples of variable modifications in https://wiki.php.net/rfc/readonly_properties_v2#proposal */ final class PropertyManipulator { /** * @var string[] */ private const ALLOWED_NOT_READONLY_ANNOTATION_CLASS_OR_ATTRIBUTES = ['Doctrine\\ORM\\Mapping\\Entity', 'Doctrine\\ORM\\Mapping\\Table']; /** * @readonly * @var \Rector\Core\NodeManipulator\AssignManipulator */ private $assignManipulator; /** * @readonly * @var \Rector\Core\PhpParser\Node\BetterNodeFinder */ private $betterNodeFinder; /** * @readonly * @var \Rector\ReadWrite\Guard\VariableToConstantGuard */ private $variableToConstantGuard; /** * @readonly * @var \Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer */ private $readWritePropertyAnalyzer; /** * @readonly * @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory */ private $phpDocInfoFactory; /** * @readonly * @var \Symplify\PackageBuilder\Php\TypeChecker */ private $typeChecker; /** * @readonly * @var \Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder */ private $propertyFetchFinder; /** * @readonly * @var \Rector\Core\Reflection\ReflectionResolver */ private $reflectionResolver; /** * @readonly * @var \Rector\NodeNameResolver\NodeNameResolver */ private $nodeNameResolver; /** * @readonly * @var \Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer */ private $phpAttributeAnalyzer; public function __construct(\Rector\Core\NodeManipulator\AssignManipulator $assignManipulator, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\ReadWrite\Guard\VariableToConstantGuard $variableToConstantGuard, \Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer $readWritePropertyAnalyzer, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \RectorPrefix20211231\Symplify\PackageBuilder\Php\TypeChecker $typeChecker, \Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder $propertyFetchFinder, \Rector\Core\Reflection\ReflectionResolver $reflectionResolver, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver, \Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer $phpAttributeAnalyzer) { $this->assignManipulator = $assignManipulator; $this->betterNodeFinder = $betterNodeFinder; $this->variableToConstantGuard = $variableToConstantGuard; $this->readWritePropertyAnalyzer = $readWritePropertyAnalyzer; $this->phpDocInfoFactory = $phpDocInfoFactory; $this->typeChecker = $typeChecker; $this->propertyFetchFinder = $propertyFetchFinder; $this->reflectionResolver = $reflectionResolver; $this->nodeNameResolver = $nodeNameResolver; $this->phpAttributeAnalyzer = $phpAttributeAnalyzer; } /** * @param \PhpParser\Node\Param|\PhpParser\Node\Stmt\Property $propertyOrPromotedParam */ public function isPropertyUsedInReadContext($propertyOrPromotedParam) : bool { $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($propertyOrPromotedParam); // @todo attributes too if ($phpDocInfo->hasByAnnotationClasses(['Doctrine\\ORM\\Mapping\\Id', 'Doctrine\\ORM\\Mapping\\Column', 'Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany', 'Doctrine\\ORM\\Mapping\\ManyToOne', 'Doctrine\\ORM\\Mapping\\OneToOne', 'JMS\\Serializer\\Annotation\\Type'])) { return \true; } $privatePropertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($propertyOrPromotedParam); foreach ($privatePropertyFetches as $privatePropertyFetch) { if ($this->readWritePropertyAnalyzer->isRead($privatePropertyFetch)) { return \true; } } // has classLike $this->$variable call? $classLike = $this->betterNodeFinder->findParentType($propertyOrPromotedParam, \PhpParser\Node\Stmt\ClassLike::class); if (!$classLike instanceof \PhpParser\Node\Stmt\ClassLike) { return \false; } return (bool) $this->betterNodeFinder->findFirst($classLike->stmts, function (\PhpParser\Node $node) : bool { if (!$node instanceof \PhpParser\Node\Expr\PropertyFetch) { return \false; } if (!$this->readWritePropertyAnalyzer->isRead($node)) { return \false; } return $node->name instanceof \PhpParser\Node\Expr; }); } /** * @param \PhpParser\Node\Param|\PhpParser\Node\Stmt\Property $propertyOrParam */ public function isPropertyChangeableExceptConstructor($propertyOrParam) : bool { $class = $this->betterNodeFinder->findParentType($propertyOrParam, \PhpParser\Node\Stmt\Class_::class); if ($class instanceof \PhpParser\Node\Stmt\Class_) { $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($class); if ($phpDocInfo->hasByAnnotationClasses(self::ALLOWED_NOT_READONLY_ANNOTATION_CLASS_OR_ATTRIBUTES)) { return \true; } if ($this->phpAttributeAnalyzer->hasPhpAttributes($class, self::ALLOWED_NOT_READONLY_ANNOTATION_CLASS_OR_ATTRIBUTES)) { return \true; } } $propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($propertyOrParam); foreach ($propertyFetches as $propertyFetch) { if ($this->isChangeableContext($propertyFetch)) { return \true; } // skip for constructor? it is allowed to set value in constructor method $classMethod = $this->betterNodeFinder->findParentType($propertyFetch, \PhpParser\Node\Stmt\ClassMethod::class); if ($classMethod instanceof \PhpParser\Node\Stmt\ClassMethod && $this->nodeNameResolver->isName($classMethod->name, \Rector\Core\ValueObject\MethodName::CONSTRUCT)) { continue; } if ($this->assignManipulator->isLeftPartOfAssign($propertyFetch)) { return \true; } } return \false; } public function isPropertyChangeable(\PhpParser\Node\Stmt\Property $property) : bool { $propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($property); foreach ($propertyFetches as $propertyFetch) { if ($this->isChangeableContext($propertyFetch)) { return \true; } if ($this->assignManipulator->isLeftPartOfAssign($propertyFetch)) { return \true; } } return \false; } /** * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch */ private function isChangeableContext($propertyFetch) : bool { $parent = $propertyFetch->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE); if (!$parent instanceof \PhpParser\Node) { return \false; } if ($this->typeChecker->isInstanceOf($parent, [\PhpParser\Node\Expr\PreInc::class, \PhpParser\Node\Expr\PreDec::class, \PhpParser\Node\Expr\PostInc::class, \PhpParser\Node\Expr\PostDec::class])) { $parent = $parent->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE); } if (!$parent instanceof \PhpParser\Node) { return \false; } if ($parent instanceof \PhpParser\Node\Arg) { $readArg = $this->variableToConstantGuard->isReadArg($parent); if (!$readArg) { return \true; } $caller = $parent->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE); if ($caller instanceof \PhpParser\Node\Expr\MethodCall || $caller instanceof \PhpParser\Node\Expr\StaticCall) { return $this->isFoundByRefParam($caller); } } return \false; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node */ private function isFoundByRefParam($node) : bool { $functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node); if ($functionLikeReflection === null) { return \false; } $parametersAcceptor = \PHPStan\Reflection\ParametersAcceptorSelector::selectSingle($functionLikeReflection->getVariants()); foreach ($parametersAcceptor->getParameters() as $parameterReflection) { if ($parameterReflection->passedByReference()->yes()) { return \true; } } return \false; } }