diff --git a/packages/ReadWrite/NodeAnalyzer/ReadWritePropertyAnalyzer.php b/packages/ReadWrite/NodeAnalyzer/ReadWritePropertyAnalyzer.php index eebdad82a89..ae8b647066b 100644 --- a/packages/ReadWrite/NodeAnalyzer/ReadWritePropertyAnalyzer.php +++ b/packages/ReadWrite/NodeAnalyzer/ReadWritePropertyAnalyzer.php @@ -12,6 +12,7 @@ use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Stmt\Unset_; +use PHPStan\Analyser\Scope; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\NodeManipulator\AssignManipulator; use Rector\Core\PhpParser\Node\BetterNodeFinder; @@ -63,7 +64,7 @@ final class ReadWritePropertyAnalyzer /** * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $node */ - public function isRead($node) : bool + public function isRead($node, Scope $scope) : bool { $parentNode = $node->getAttribute(AttributeKey::PARENT_NODE); if (!$parentNode instanceof Node) { @@ -86,12 +87,12 @@ final class ReadWritePropertyAnalyzer if ($this->assignManipulator->isLeftPartOfAssign($parentNode)) { return \false; } - if (!$this->isArrayDimFetchInImpureFunction($parentNode, $node)) { + if (!$this->isArrayDimFetchInImpureFunction($parentNode, $node, $scope)) { return $this->isNotInsideIssetUnset($parentNode); } return \false; } - private function isArrayDimFetchInImpureFunction(ArrayDimFetch $arrayDimFetch, Node $node) : bool + private function isArrayDimFetchInImpureFunction(ArrayDimFetch $arrayDimFetch, Node $node, Scope $scope) : bool { if ($arrayDimFetch->var === $node) { $arg = $this->betterNodeFinder->findParentType($arrayDimFetch, Arg::class); @@ -100,7 +101,7 @@ final class ReadWritePropertyAnalyzer if (!$parentArg instanceof FuncCall) { return \false; } - return !$this->pureFunctionDetector->detect($parentArg); + return !$this->pureFunctionDetector->detect($parentArg, $scope); } } return \false; diff --git a/rules/CodeQuality/Rector/Expression/TernaryFalseExpressionToIfRector.php b/rules/CodeQuality/Rector/Expression/TernaryFalseExpressionToIfRector.php index 94fce788c3b..4c44d930a56 100644 --- a/rules/CodeQuality/Rector/Expression/TernaryFalseExpressionToIfRector.php +++ b/rules/CodeQuality/Rector/Expression/TernaryFalseExpressionToIfRector.php @@ -8,14 +8,16 @@ use PhpParser\Node\Expr; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\If_; +use PHPStan\Analyser\Scope; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\DeadCode\SideEffect\SideEffectNodeDetector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\CodeQuality\Rector\Expression\TernaryFalseExpressionToIfRector\TernaryFalseExpressionToIfRectorTest */ -final class TernaryFalseExpressionToIfRector extends AbstractRector +final class TernaryFalseExpressionToIfRector extends AbstractScopeAwareRector { /** * @readonly @@ -60,7 +62,7 @@ CODE_SAMPLE /** * @param Expression $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { if (!$node->expr instanceof Ternary) { return null; @@ -69,7 +71,7 @@ CODE_SAMPLE if (!$ternary->if instanceof Expr) { return null; } - if ($this->sideEffectNodeDetector->detect($ternary->else)) { + if ($this->sideEffectNodeDetector->detect($ternary->else, $scope)) { return null; } return new If_($ternary->cond, ['stmts' => [new Expression($ternary->if)]]); diff --git a/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php b/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php index 698b0e43835..f71539fc30a 100644 --- a/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php +++ b/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php @@ -15,15 +15,17 @@ use PhpParser\Node\Stmt\Foreach_; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Namespace_; +use PHPStan\Analyser\Scope; use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\DeadCode\SideEffect\SideEffectNodeDetector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\DeadCode\Rector\Assign\RemoveDoubleAssignRector\RemoveDoubleAssignRectorTest */ -final class RemoveDoubleAssignRector extends AbstractRector +final class RemoveDoubleAssignRector extends AbstractScopeAwareRector { /** * @readonly @@ -52,7 +54,7 @@ CODE_SAMPLE /** * @param Foreach_|FileWithoutNamespace|If_|Namespace_|ClassMethod|Function_|Closure $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { $stmts = $node->stmts; if ($stmts === null) { @@ -86,7 +88,7 @@ CODE_SAMPLE } // detect call expression has side effect // no calls on right, could hide e.g. array_pop()|array_shift() - if ($this->sideEffectNodeDetector->detectCallExpr($stmt->expr->expr)) { + if ($this->sideEffectNodeDetector->detectCallExpr($stmt->expr->expr, $scope)) { continue; } if (!$stmt->expr->var instanceof Variable && !$stmt->expr->var instanceof PropertyFetch && !$stmt->expr->var instanceof StaticPropertyFetch) { diff --git a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php index 467827e2593..c6ae69ee9e9 100644 --- a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php +++ b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php @@ -121,7 +121,7 @@ CODE_SAMPLE if ($this->isUsed($node, $variable, $scope)) { return $this->refactorUsedVariable($node, $scope); } - if ($this->hasCallLikeInAssignExpr($node->expr)) { + if ($this->hasCallLikeInAssignExpr($node->expr, $scope)) { // keep the expr, can have side effect return $this->cleanCastedExpr($node->expr); } @@ -136,10 +136,10 @@ CODE_SAMPLE $castedExpr = $expr->expr; return $this->cleanCastedExpr($castedExpr); } - private function hasCallLikeInAssignExpr(Expr $expr) : bool + private function hasCallLikeInAssignExpr(Expr $expr, Scope $scope) : bool { - return (bool) $this->betterNodeFinder->findFirst($expr, function (Node $subNode) : bool { - return $this->sideEffectNodeDetector->detectCallExpr($subNode); + return (bool) $this->betterNodeFinder->findFirst($expr, function (Node $subNode) use($scope) : bool { + return $this->sideEffectNodeDetector->detectCallExpr($subNode, $scope); }); } private function shouldSkip(Assign $assign) : bool @@ -178,7 +178,7 @@ CODE_SAMPLE } /** @var FuncCall|MethodCall|New_|NullsafeMethodCall|StaticCall $expr */ $expr = $assign->expr; - if (!$this->sideEffectNodeDetector->detectCallExpr($expr)) { + if (!$this->sideEffectNodeDetector->detectCallExpr($expr, $scope)) { return \false; } return $this->isUsedInAssignExpr($expr, $assign, $scope); diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php index 08df5b353ab..107798e6232 100644 --- a/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php +++ b/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.php @@ -7,9 +7,11 @@ use PhpParser\Node; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use PHPStan\Analyser\Scope; use Rector\Core\NodeManipulator\PropertyManipulator; use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\Core\ValueObject\MethodName; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\Core\ValueObject\Visibility; @@ -20,7 +22,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPromotedPropertyRector\RemoveUnusedPromotedPropertyRectorTest */ -final class RemoveUnusedPromotedPropertyRector extends AbstractRector implements MinPhpVersionInterface +final class RemoveUnusedPromotedPropertyRector extends AbstractScopeAwareRector implements MinPhpVersionInterface { /** * @readonly @@ -86,7 +88,7 @@ CODE_SAMPLE /** * @param Class_ $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { $constructClassMethod = $node->getMethod(MethodName::CONSTRUCT); if (!$constructClassMethod instanceof ClassMethod) { @@ -102,7 +104,7 @@ CODE_SAMPLE if (!$this->visibilityManipulator->hasVisibility($param, Visibility::PRIVATE)) { continue; } - if ($this->propertyManipulator->isPropertyUsedInReadContext($node, $param)) { + if ($this->propertyManipulator->isPropertyUsedInReadContext($node, $param, $scope)) { continue; } $paramName = $this->getName($param); diff --git a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php index 1d86b9e3733..24caced32f5 100644 --- a/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php +++ b/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php @@ -7,16 +7,18 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Nop; use PhpParser\Node\Stmt\Property; +use PHPStan\Analyser\Scope; use Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface; use Rector\Core\NodeManipulator\PropertyManipulator; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\Removing\NodeManipulator\ComplexNodeRemover; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\DeadCode\Rector\Property\RemoveUnusedPrivatePropertyRector\RemoveUnusedPrivatePropertyRectorTest */ -final class RemoveUnusedPrivatePropertyRector extends AbstractRector implements AllowEmptyConfigurableRectorInterface +final class RemoveUnusedPrivatePropertyRector extends AbstractScopeAwareRector implements AllowEmptyConfigurableRectorInterface { /** * @api @@ -76,7 +78,7 @@ CODE_SAMPLE /** * @param Class_ $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { $hasRemoved = \false; foreach ($node->stmts as $key => $property) { @@ -86,12 +88,12 @@ CODE_SAMPLE if ($this->shouldSkipProperty($property)) { continue; } - if ($this->propertyManipulator->isPropertyUsedInReadContext($node, $property)) { + if ($this->propertyManipulator->isPropertyUsedInReadContext($node, $property, $scope)) { continue; } // use different variable to avoid re-assign back $hasRemoved to false // when already asssigned to true - $isRemoved = $this->complexNodeRemover->removePropertyAndUsages($node, $property, $this->removeAssignSideEffect); + $isRemoved = $this->complexNodeRemover->removePropertyAndUsages($node, $property, $this->removeAssignSideEffect, $scope); if ($isRemoved) { $this->processRemoveSameLineComment($node, $property, $key); $hasRemoved = \true; diff --git a/rules/DeadCode/SideEffect/PureFunctionDetector.php b/rules/DeadCode/SideEffect/PureFunctionDetector.php index da5003fc5ff..4998c172876 100644 --- a/rules/DeadCode/SideEffect/PureFunctionDetector.php +++ b/rules/DeadCode/SideEffect/PureFunctionDetector.php @@ -5,6 +5,7 @@ namespace Rector\DeadCode\SideEffect; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name; +use PHPStan\Analyser\Scope; use PHPStan\Reflection\Native\NativeFunctionReflection; use PHPStan\Reflection\ReflectionProvider; use Rector\NodeNameResolver\NodeNameResolver; @@ -240,13 +241,12 @@ final class PureFunctionDetector $this->nodeNameResolver = $nodeNameResolver; $this->reflectionProvider = $reflectionProvider; } - public function detect(FuncCall $funcCall) : bool + public function detect(FuncCall $funcCall, Scope $scope) : bool { $funcCallName = $this->nodeNameResolver->getName($funcCall); if ($funcCallName === null) { return \false; } - $scope = $funcCall->getAttribute(AttributeKey::SCOPE); $name = new Name($funcCallName); $hasFunction = $this->reflectionProvider->hasFunction($name, $scope); if (!$hasFunction) { diff --git a/rules/DeadCode/SideEffect/SideEffectNodeDetector.php b/rules/DeadCode/SideEffect/SideEffectNodeDetector.php index 274f9e5915c..3e896abcb79 100644 --- a/rules/DeadCode/SideEffect/SideEffectNodeDetector.php +++ b/rules/DeadCode/SideEffect/SideEffectNodeDetector.php @@ -19,6 +19,7 @@ use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Scalar\Encapsed; +use PHPStan\Analyser\Scope; use PHPStan\Type\ConstantType; use PHPStan\Type\ObjectType; use Rector\NodeTypeResolver\NodeTypeResolver; @@ -47,7 +48,7 @@ final class SideEffectNodeDetector $this->nodeTypeResolver = $nodeTypeResolver; $this->pureFunctionDetector = $pureFunctionDetector; } - public function detect(Expr $expr) : bool + public function detect(Expr $expr, Scope $scope) : bool { if ($expr instanceof Assign) { return \true; @@ -62,7 +63,7 @@ final class SideEffectNodeDetector return \false; } if ($expr instanceof FuncCall) { - return !$this->pureFunctionDetector->detect($expr); + return !$this->pureFunctionDetector->detect($expr, $scope); } if ($expr instanceof Variable || $expr instanceof ArrayDimFetch) { $variable = $this->resolveVariable($expr); @@ -71,7 +72,7 @@ final class SideEffectNodeDetector } return \true; } - public function detectCallExpr(Node $node) : bool + public function detectCallExpr(Node $node, Scope $scope) : bool { if (!$node instanceof Expr) { return \false; @@ -87,7 +88,7 @@ final class SideEffectNodeDetector return \true; } if ($node instanceof FuncCall) { - return !$this->pureFunctionDetector->detect($node); + return !$this->pureFunctionDetector->detect($node, $scope); } return \false; } diff --git a/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php b/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php index 2bfe89564ba..3c45b34d494 100644 --- a/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php +++ b/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php @@ -14,10 +14,12 @@ use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Property; use PhpParser\NodeTraverser; +use PHPStan\Analyser\Scope; use Rector\Core\NodeAnalyzer\ParamAnalyzer; use Rector\Core\NodeManipulator\PropertyFetchAssignManipulator; use Rector\Core\NodeManipulator\PropertyManipulator; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\Core\ValueObject\MethodName; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\Core\ValueObject\Visibility; @@ -31,7 +33,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; * * @see \Rector\Tests\Php81\Rector\Property\ReadOnlyPropertyRector\ReadOnlyPropertyRectorTest */ -final class ReadOnlyPropertyRector extends AbstractRector implements MinPhpVersionInterface +final class ReadOnlyPropertyRector extends AbstractScopeAwareRector implements MinPhpVersionInterface { /** * @readonly @@ -102,12 +104,12 @@ CODE_SAMPLE /** * @param Property|Param $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { if ($node instanceof Param) { - return $this->refactorParam($node); + return $this->refactorParam($node, $scope); } - return $this->refactorProperty($node); + return $this->refactorProperty($node, $scope); } public function provideMinPhpVersion() : int { @@ -124,7 +126,7 @@ CODE_SAMPLE } return $class->isReadonly(); } - private function refactorProperty(Property $property) : ?Property + private function refactorProperty(Property $property, Scope $scope) : ?Property { // 1. is property read-only? if ($property->isReadonly()) { @@ -142,7 +144,7 @@ CODE_SAMPLE if (!$this->visibilityManipulator->hasVisibility($property, Visibility::PRIVATE)) { return null; } - if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($property)) { + if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($property, $scope)) { return null; } if ($this->propertyFetchAssignManipulator->isAssignedMultipleTimesInConstructor($property)) { @@ -158,7 +160,7 @@ CODE_SAMPLE } return $property; } - private function refactorParam(Param $param) : ?\PhpParser\Node\Param + private function refactorParam(Param $param, Scope $scope) : ?\PhpParser\Node\Param { if (!$this->visibilityManipulator->hasVisibility($param, Visibility::PRIVATE)) { return null; @@ -167,7 +169,7 @@ CODE_SAMPLE return null; } // promoted property? - if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($param)) { + if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($param, $scope)) { return null; } if ($this->visibilityManipulator->isReadonly($param)) { diff --git a/rules/Privatization/Rector/Property/ChangeReadOnlyPropertyWithDefaultValueToConstantRector.php b/rules/Privatization/Rector/Property/ChangeReadOnlyPropertyWithDefaultValueToConstantRector.php index 6b186dff1e0..82dc8ab50e8 100644 --- a/rules/Privatization/Rector/Property/ChangeReadOnlyPropertyWithDefaultValueToConstantRector.php +++ b/rules/Privatization/Rector/Property/ChangeReadOnlyPropertyWithDefaultValueToConstantRector.php @@ -8,9 +8,11 @@ use PhpParser\Node\Expr; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; use PhpParser\Node\Stmt\PropertyProperty; +use PHPStan\Analyser\Scope; use PHPStan\Type\ObjectType; use Rector\Core\NodeManipulator\PropertyManipulator; use Rector\Core\Rector\AbstractRector; +use Rector\Core\Rector\AbstractScopeAwareRector; use Rector\Privatization\NodeFactory\ClassConstantFactory; use Rector\Privatization\NodeReplacer\PropertyFetchWithConstFetchReplacer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -18,7 +20,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @see \Rector\Tests\Privatization\Rector\Property\ChangeReadOnlyPropertyWithDefaultValueToConstantRector\ChangeReadOnlyPropertyWithDefaultValueToConstantRectorTest */ -final class ChangeReadOnlyPropertyWithDefaultValueToConstantRector extends AbstractRector +final class ChangeReadOnlyPropertyWithDefaultValueToConstantRector extends AbstractScopeAwareRector { /** * @readonly @@ -93,7 +95,7 @@ CODE_SAMPLE /** * @param Property $node */ - public function refactor(Node $node) : ?Node + public function refactorWithScope(Node $node, Scope $scope) : ?Node { if ($this->shouldSkip($node)) { return null; @@ -112,7 +114,7 @@ CODE_SAMPLE return null; } // is property read only? - if ($this->propertyManipulator->isPropertyChangeable($class, $node)) { + if ($this->propertyManipulator->isPropertyChangeable($class, $node, $scope)) { return null; } /** @var Class_ $classLike */ diff --git a/rules/Removing/NodeManipulator/ComplexNodeRemover.php b/rules/Removing/NodeManipulator/ComplexNodeRemover.php index c865552ccba..1caab82f18b 100644 --- a/rules/Removing/NodeManipulator/ComplexNodeRemover.php +++ b/rules/Removing/NodeManipulator/ComplexNodeRemover.php @@ -15,6 +15,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Property; +use PHPStan\Analyser\Scope; use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer; use Rector\Core\PhpParser\Comparing\NodeComparator; use Rector\Core\PhpParser\Node\BetterNodeFinder; @@ -71,12 +72,12 @@ final class ComplexNodeRemover $this->propertyFetchAnalyzer = $propertyFetchAnalyzer; $this->nodeComparator = $nodeComparator; } - public function removePropertyAndUsages(Class_ $class, Property $property, bool $removeAssignSideEffect) : bool + public function removePropertyAndUsages(Class_ $class, Property $property, bool $removeAssignSideEffect, Scope $scope) : bool { $propertyName = $this->nodeNameResolver->getName($property); $totalPropertyFetch = $this->propertyFetchAnalyzer->countLocalPropertyFetchName($class, $propertyName); $expressions = []; - $this->simpleCallableNodeTraverser->traverseNodesWithCallable($class->stmts, function (Node $node) use($removeAssignSideEffect, $propertyName, &$totalPropertyFetch, &$expressions) : ?Node { + $this->simpleCallableNodeTraverser->traverseNodesWithCallable($class->stmts, function (Node $node) use($removeAssignSideEffect, $propertyName, &$totalPropertyFetch, &$expressions, $scope) : ?Node { // here should be checked all expr like stmts that can hold assign, e.f. if, foreach etc. etc. if (!$node instanceof Expression) { return null; @@ -102,7 +103,7 @@ final class ComplexNodeRemover $currentTotalPropertyFetch = $totalPropertyFetch; foreach ($propertyFetches as $propertyFetch) { if ($this->nodeNameResolver->isName($propertyFetch->name, $propertyName)) { - if (!$removeAssignSideEffect && $this->sideEffectNodeDetector->detect($assign->expr)) { + if (!$removeAssignSideEffect && $this->sideEffectNodeDetector->detect($assign->expr, $scope)) { return null; } --$totalPropertyFetch; diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 096a1be68d1..d01d920133a 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '6482c594e4b554a814165d11baeece9498868caa'; + public const PACKAGE_VERSION = '499fdbc3af1779929444c170a778678e28be957a'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-05-14 09:30:25'; + public const RELEASE_DATE = '2023-05-14 16:57:42'; /** * @var int */ diff --git a/src/NodeManipulator/PropertyManipulator.php b/src/NodeManipulator/PropertyManipulator.php index 07c96d67181..53bb94099a9 100644 --- a/src/NodeManipulator/PropertyManipulator.php +++ b/src/NodeManipulator/PropertyManipulator.php @@ -155,7 +155,7 @@ final class PropertyManipulator /** * @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $propertyOrPromotedParam */ - public function isPropertyUsedInReadContext(Class_ $class, $propertyOrPromotedParam) : bool + public function isPropertyUsedInReadContext(Class_ $class, $propertyOrPromotedParam, Scope $scope) : bool { $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($propertyOrPromotedParam); if ($this->isAllowedReadOnly($propertyOrPromotedParam, $phpDocInfo)) { @@ -163,7 +163,7 @@ final class PropertyManipulator } $privatePropertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($class, $propertyOrPromotedParam); foreach ($privatePropertyFetches as $privatePropertyFetch) { - if ($this->readWritePropertyAnalyzer->isRead($privatePropertyFetch)) { + if ($this->readWritePropertyAnalyzer->isRead($privatePropertyFetch, $scope)) { return \true; } } @@ -172,11 +172,11 @@ final class PropertyManipulator if (!$classLike instanceof ClassLike) { return \false; } - return (bool) $this->betterNodeFinder->findFirst($classLike->stmts, function (Node $node) : bool { + return (bool) $this->betterNodeFinder->findFirst($classLike->stmts, function (Node $node) use($scope) : bool { if (!$node instanceof PropertyFetch) { return \false; } - if (!$this->readWritePropertyAnalyzer->isRead($node)) { + if (!$this->readWritePropertyAnalyzer->isRead($node, $scope)) { return \false; } return $node->name instanceof Expr; @@ -185,7 +185,7 @@ final class PropertyManipulator /** * @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $propertyOrParam */ - public function isPropertyChangeableExceptConstructor($propertyOrParam) : bool + public function isPropertyChangeableExceptConstructor($propertyOrParam, Scope $scope) : bool { $class = $this->betterNodeFinder->findParentType($propertyOrParam, Class_::class); // does not have parent type ClassLike? Possibly parent is changed by other rule @@ -201,7 +201,7 @@ final class PropertyManipulator } $propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($class, $propertyOrParam); foreach ($propertyFetches as $propertyFetch) { - if ($this->isChangeableContext($propertyFetch)) { + if ($this->isChangeableContext($propertyFetch, $scope)) { return \true; } // skip for constructor? it is allowed to set value in constructor method @@ -220,11 +220,11 @@ final class PropertyManipulator } return \false; } - public function isPropertyChangeable(Class_ $class, Property $property) : bool + public function isPropertyChangeable(Class_ $class, Property $property, Scope $scope) : bool { $propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($class, $property); foreach ($propertyFetches as $propertyFetch) { - if ($this->isChangeableContext($propertyFetch)) { + if ($this->isChangeableContext($propertyFetch, $scope)) { return \true; } if ($this->assignManipulator->isLeftPartOfAssign($propertyFetch)) { @@ -289,7 +289,7 @@ final class PropertyManipulator /** * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch */ - private function isChangeableContext($propertyFetch) : bool + private function isChangeableContext($propertyFetch, Scope $scope) : bool { $parentNode = $propertyFetch->getAttribute(AttributeKey::PARENT_NODE); if (!$parentNode instanceof Node) { @@ -312,7 +312,7 @@ final class PropertyManipulator } } if ($parentNode instanceof ArrayDimFetch) { - return !$this->readWritePropertyAnalyzer->isRead($propertyFetch); + return !$this->readWritePropertyAnalyzer->isRead($propertyFetch, $scope); } return $parentNode instanceof Unset_; } diff --git a/vendor/autoload.php b/vendor/autoload.php index 6131117a8f3..2a6f8dd9fd7 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) { require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInite690da08c00c0d8835a53c8379f74349::getLoader(); +return ComposerAutoloaderInitb9235c9149ee5db18dbd9ae10830c14d::getLoader(); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 6c87da6af6f..0046aa606d2 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInite690da08c00c0d8835a53c8379f74349 +class ComposerAutoloaderInitb9235c9149ee5db18dbd9ae10830c14d { private static $loader; @@ -22,17 +22,17 @@ class ComposerAutoloaderInite690da08c00c0d8835a53c8379f74349 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInite690da08c00c0d8835a53c8379f74349', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitb9235c9149ee5db18dbd9ae10830c14d', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInite690da08c00c0d8835a53c8379f74349', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitb9235c9149ee5db18dbd9ae10830c14d', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInite690da08c00c0d8835a53c8379f74349::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInite690da08c00c0d8835a53c8379f74349::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 7c32c14ca73..fc67a3ce508 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInite690da08c00c0d8835a53c8379f74349 +class ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', @@ -3111,9 +3111,9 @@ class ComposerStaticInite690da08c00c0d8835a53c8379f74349 public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInite690da08c00c0d8835a53c8379f74349::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInite690da08c00c0d8835a53c8379f74349::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInite690da08c00c0d8835a53c8379f74349::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitb9235c9149ee5db18dbd9ae10830c14d::$classMap; }, null, ClassLoader::class); }