[Privatization] Skip ChangeGlobalVariablesToPropertiesRector on read only global variable (#442)

* [Privatization] Skip ChangeGlobalVariablesToPropertiesRector on read only global variable

* Fixed 🎉

* clean up

* clean up
This commit is contained in:
Abdul Malik Ikhsan 2021-07-15 20:52:06 +07:00 committed by GitHub
parent b2c0a05d56
commit a0f2ad9789
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 5 deletions

View File

@ -0,0 +1,17 @@
<?php
namespace Rector\Tests\Privatization\Rector\ClassMethod\ChangeGlobalVariablesToPropertiesRector\Fixture;
$variable = 'value';
class SkipReadOnlyGlobal
{
public function go()
{
global $variable;
echo $variable;
}
}
?>

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Privatization\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
@ -95,7 +96,7 @@ CODE_SAMPLE
return null;
}
$this->collectGlobalVariableNamesAndRefactorToPropertyFetch($node);
$this->collectGlobalVariableNamesAndRefactorToPropertyFetch($classLike, $node);
if ($this->globalVariableNames === []) {
return null;
@ -108,13 +109,13 @@ CODE_SAMPLE
return $node;
}
private function collectGlobalVariableNamesAndRefactorToPropertyFetch(ClassMethod $classMethod): void
private function collectGlobalVariableNamesAndRefactorToPropertyFetch(Class_ $class, ClassMethod $classMethod): void
{
$this->globalVariableNames = [];
$this->traverseNodesWithCallable($classMethod, function (Node $node): ?PropertyFetch {
$this->traverseNodesWithCallable($classMethod, function (Node $node) use ($class): ?PropertyFetch {
if ($node instanceof Global_) {
$this->refactorGlobal($node);
$this->refactorGlobal($class, $node);
return null;
}
@ -126,7 +127,7 @@ CODE_SAMPLE
});
}
private function refactorGlobal(Global_ $global): void
private function refactorGlobal(Class_ $class, Global_ $global): void
{
foreach ($global->vars as $var) {
$varName = $this->getName($var);
@ -134,6 +135,10 @@ CODE_SAMPLE
return;
}
if ($this->isReadOnly($class, $varName)) {
return;
}
$this->globalVariableNames[] = $varName;
}
@ -154,4 +159,32 @@ CODE_SAMPLE
return $this->nodeFactory->createPropertyFetch('this', $variableName);
}
private function isReadOnly(Class_ $class, string $globalVariableName): bool
{
/** @var ClassMethod[] $classMethods */
$classMethods = $this->betterNodeFinder->findInstanceOf($class, ClassMethod::class);
foreach ($classMethods as $classMethod) {
$isReAssign = (bool) $this->betterNodeFinder->findFirst((array) $classMethod->stmts, function (Node $node) use (
$globalVariableName
): bool {
if (! $node instanceof Assign) {
return false;
}
if ($node->var instanceof Variable) {
return $this->nodeNameResolver->isName($node->var, $globalVariableName);
}
if ($node->var instanceof PropertyFetch) {
return $this->nodeNameResolver->isName($node->var, $globalVariableName);
}
return false;
});
if ($isReAssign) {
return false;
}
}
return true;
}
}