[RemovingStatic] Add LocallyCalledStaticMethodToNonStaticRector (#4181)

* update docs

* [RemovingStatic] Add LocallyCalledStaticMethodToNonStaticRector

* [rector] [RemovingStatic] Add LocallyCalledStaticMethodToNonStaticRector

* [cs] [RemovingStatic] Add LocallyCalledStaticMethodToNonStaticRector

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-09-10 09:27:03 +02:00 committed by GitHub
parent db9d18227e
commit 44f383038f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 613 additions and 93 deletions

View File

@ -1,4 +1,4 @@
# All 568 Rectors Overview
# All 575 Rectors Overview
- [Projects](#projects)
---
@ -15,7 +15,9 @@
- [Doctrine](#doctrine) (17)
- [DoctrineCodeQuality](#doctrinecodequality) (8)
- [DoctrineGedmoToKnplabs](#doctrinegedmotoknplabs) (7)
- [Downgrade](#downgrade) (6)
- [DowngradePhp72](#downgradephp72) (2)
- [DowngradePhp74](#downgradephp74) (3)
- [DowngradePhp80](#downgradephp80) (6)
- [DynamicTypeAnalysis](#dynamictypeanalysis) (3)
- [FileSystemRector](#filesystemrector) (1)
- [Generic](#generic) (38)
@ -26,7 +28,7 @@
- [MockeryToProphecy](#mockerytoprophecy) (2)
- [MockistaToMockery](#mockistatomockery) (2)
- [MysqlToMysqli](#mysqltomysqli) (4)
- [Naming](#naming) (6)
- [Naming](#naming) (7)
- [Nette](#nette) (16)
- [NetteCodeQuality](#nettecodequality) (6)
- [NetteKdyby](#nettekdyby) (4)
@ -57,7 +59,7 @@
- [Polyfill](#polyfill) (2)
- [Privatization](#privatization) (7)
- [RectorGenerator](#rectorgenerator) (1)
- [RemovingStatic](#removingstatic) (4)
- [RemovingStatic](#removingstatic) (5)
- [Renaming](#renaming) (8)
- [Restoration](#restoration) (7)
- [SOLID](#solid) (12)
@ -906,7 +908,7 @@ Simplify `foreach` loops into `in_array` when possible
```diff
-foreach ($items as $item) {
- if ($item === "something") {
- if ($item === 'something') {
- return true;
- }
-}
@ -2844,7 +2846,8 @@ Remove duplicated instanceof in one call
```diff
class SomeClass
{
public function run($value)
- public function run($value)
+ public function run($value): void
{
- $isIt = $value instanceof A || $value instanceof A;
- $isIt = $value instanceof A && $value instanceof A;
@ -3929,7 +3932,6 @@ Change database type "bigint" for @var/type declaration to string
Change array to ArrayCollection in setParameters method of query builder
```diff
-
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityRepository;
+use Doctrine\ORM\Query\Parameter;
@ -4481,50 +4483,12 @@ Change Tree from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
<br><br>
## Downgrade
### `ArrowFunctionToAnonymousFunctionRector`
- class: [`Rector\Downgrade\Rector\ArrowFunction\ArrowFunctionToAnonymousFunctionRector`](/rules/downgrade/src/Rector/ArrowFunction/ArrowFunctionToAnonymousFunctionRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/ArrowFunction/ArrowFunctionToAnonymousFunctionRector/Fixture)
Replace arrow functions with anonymous functions
```diff
class SomeClass
{
public function run()
{
$delimiter = ",";
- $callable = fn($matches) => $delimiter . strtolower($matches[1]);
+ $callable = function ($matches) use ($delimiter) {
+ return $delimiter . strtolower($matches[1]);
+ };
}
}
```
<br><br>
### `DowngradeNullCoalescingOperatorRector`
- class: [`Rector\Downgrade\Rector\Coalesce\DowngradeNullCoalescingOperatorRector`](/rules/downgrade/src/Rector/Coalesce/DowngradeNullCoalescingOperatorRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/Coalesce/DowngradeNullCoalescingOperatorRector/Fixture)
Remove null coalescing operator ??=
```diff
$array = [];
-$array['user_id'] ??= 'value';
+$array['user_id'] = $array['user_id'] ?? 'value';
```
<br><br>
## DowngradePhp72
### `DowngradeParamObjectTypeDeclarationRector`
- class: [`Rector\Downgrade\Rector\FunctionLike\DowngradeParamObjectTypeDeclarationRector`](/rules/downgrade/src/Rector/FunctionLike/DowngradeParamObjectTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/FunctionLike/DowngradeParamObjectTypeDeclarationRector/Fixture)
- class: [`Rector\DowngradePhp72\Rector\FunctionLike\DowngradeParamObjectTypeDeclarationRector`](/rules/downgrade-php72/src/Rector/FunctionLike/DowngradeParamObjectTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade-php72/tests/Rector/FunctionLike/DowngradeParamObjectTypeDeclarationRector/Fixture)
Remove the 'object' param type, add a @param tag instead
@ -4547,8 +4511,8 @@ Remove the 'object' param type, add a @param tag instead
### `DowngradeReturnObjectTypeDeclarationRector`
- class: [`Rector\Downgrade\Rector\FunctionLike\DowngradeReturnObjectTypeDeclarationRector`](/rules/downgrade/src/Rector/FunctionLike/DowngradeReturnObjectTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/FunctionLike/DowngradeReturnObjectTypeDeclarationRector/Fixture)
- class: [`Rector\DowngradePhp72\Rector\FunctionLike\DowngradeReturnObjectTypeDeclarationRector`](/rules/downgrade-php72/src/Rector/FunctionLike/DowngradeReturnObjectTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade-php72/tests/Rector/FunctionLike/DowngradeReturnObjectTypeDeclarationRector/Fixture)
Remove the 'object' function type, add a @return tag instead
@ -4570,10 +4534,50 @@ Remove the 'object' function type, add a @return tag instead
<br><br>
## DowngradePhp74
### `ArrowFunctionToAnonymousFunctionRector`
- class: [`Rector\DowngradePhp74\Rector\ArrowFunction\ArrowFunctionToAnonymousFunctionRector`](/rules/downgrade-php74/src/Rector/ArrowFunction/ArrowFunctionToAnonymousFunctionRector.php)
- [test fixtures](/rules/downgrade-php74/tests/Rector/ArrowFunction/ArrowFunctionToAnonymousFunctionRector/Fixture)
Replace arrow functions with anonymous functions
```diff
class SomeClass
{
public function run()
{
$delimiter = ",";
- $callable = fn($matches) => $delimiter . strtolower($matches[1]);
+ $callable = function ($matches) use ($delimiter) {
+ return $delimiter . strtolower($matches[1]);
+ };
}
}
```
<br><br>
### `DowngradeNullCoalescingOperatorRector`
- class: [`Rector\DowngradePhp74\Rector\Coalesce\DowngradeNullCoalescingOperatorRector`](/rules/downgrade-php74/src/Rector/Coalesce/DowngradeNullCoalescingOperatorRector.php)
- [test fixtures](/rules/downgrade-php74/tests/Rector/Coalesce/DowngradeNullCoalescingOperatorRector/Fixture)
Remove null coalescing operator ??=
```diff
$array = [];
-$array['user_id'] ??= 'value';
+$array['user_id'] = $array['user_id'] ?? 'value';
```
<br><br>
### `DowngradeTypedPropertyRector`
- class: [`Rector\Downgrade\Rector\Property\DowngradeTypedPropertyRector`](/rules/downgrade/src/Rector/Property/DowngradeTypedPropertyRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/Property/DowngradeTypedPropertyRector/Fixture)
- class: [`Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector`](/rules/downgrade-php74/src/Rector/Property/DowngradeTypedPropertyRector.php)
- [test fixtures](/rules/downgrade-php74/tests/Rector/Property/DowngradeTypedPropertyRector/Fixture)
Changes property type definition from type definitions to `@var` annotations.
@ -4590,30 +4594,153 @@ Changes property type definition from type definitions to `@var` annotations.
<br><br>
### `DowngradeUnionTypeToDocBlockRector`
## DowngradePhp80
- class: [`Rector\Downgrade\Rector\Property\DowngradeUnionTypeToDocBlockRector`](/rules/downgrade/src/Rector/Property/DowngradeUnionTypeToDocBlockRector.php)
- [test fixtures](/rules/downgrade/tests/Rector/Property/DowngradeUnionTypeToDocBlockRector/Fixture)
### `DowngradeParamMixedTypeDeclarationRector`
Downgrade union types to doc block
- class: [`Rector\DowngradePhp80\Rector\FunctionLike\DowngradeParamMixedTypeDeclarationRector`](/rules/downgrade-php80/src/Rector/FunctionLike/DowngradeParamMixedTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/FunctionLike/DowngradeParamMixedTypeDeclarationRector/Fixture)
Remove the 'mixed' param type, add a @param tag instead
```diff
<?php
class SomeClass
{
- public function someFunction(mixed $anything)
+ /**
+ * @param mixed $anything
+ */
+ public function someFunction($anything)
{
}
}
```
<br><br>
### `DowngradeReturnMixedTypeDeclarationRector`
- class: [`Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnMixedTypeDeclarationRector`](/rules/downgrade-php80/src/Rector/FunctionLike/DowngradeReturnMixedTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/FunctionLike/DowngradeReturnMixedTypeDeclarationRector/Fixture)
Remove the 'mixed' function type, add a @return tag instead
```diff
<?php
class SomeClass
{
- public function getAnything(bool $flag): mixed
+ /**
+ * @return mixed
+ */
+ public function getAnything(bool $flag)
{
if ($flag) {
return 1;
}
return 'Hello world'
}
}
```
<br><br>
### `DowngradeReturnStaticTypeDeclarationRector`
- class: [`Rector\DowngradePhp80\Rector\FunctionLike\DowngradeReturnStaticTypeDeclarationRector`](/rules/downgrade-php80/src/Rector/FunctionLike/DowngradeReturnStaticTypeDeclarationRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/FunctionLike/DowngradeReturnStaticTypeDeclarationRector/Fixture)
Remove the 'static' function type, add a @return tag instead
```diff
<?php
class SomeClass
{
- public function getStatic(): static
+ /**
+ * @return static
+ */
+ public function getStatic()
{
return new static();
}
}
```
<br><br>
### `DowngradeUnionTypeParamDeclarationRector`
- class: [`Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeParamDeclarationRector`](/rules/downgrade-php80/src/Rector/FunctionLike/DowngradeUnionTypeParamDeclarationRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/FunctionLike/DowngradeUnionTypeParamDeclarationRector/Fixture)
Remove the union type params, add @param tags instead
```diff
<?php
class SomeClass
{
- public function echoInput(string|int $input)
+ /**
+ * @param string|int $input
+ */
+ public function echoInput($input)
{
echo $input;
}
}
```
<br><br>
### `DowngradeUnionTypeReturnDeclarationRector`
- class: [`Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeReturnDeclarationRector`](/rules/downgrade-php80/src/Rector/FunctionLike/DowngradeUnionTypeReturnDeclarationRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/FunctionLike/DowngradeUnionTypeReturnDeclarationRector/Fixture)
Remove returning union types, add a @return tag instead
```diff
<?php
class SomeClass
{
- public function getSomeObject(bool $flag): string|int
+ /**
+ * @return string|int
+ */
+ public function getSomeObject(bool $flag)
{
if ($flag) {
return 1;
}
return 'Hello world';
}
}
```
<br><br>
### `DowngradeUnionTypeTypedPropertyRector`
- class: [`Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector`](/rules/downgrade-php80/src/Rector/Property/DowngradeUnionTypeTypedPropertyRector.php)
- [test fixtures](/rules/downgrade-php80/tests/Rector/Property/DowngradeUnionTypeTypedPropertyRector/Fixture)
Removes union type property type definition, adding `@var` annotations instead.
```diff
class SomeClass
{
- public int|string $value;
- private string|int $property;
+ /**
+ * @var int|string
+ */
+ public $value;
- public function run(): int|string
+ /**
+ * @return int|string
+ */
+ public function run()
{
$this->value;
}
+ * @var string|int
+ */
+ private $property;
}
```
@ -6726,6 +6853,30 @@ Change is method names to start with is/has/was
<br><br>
### `RenameForeachValueVariableToMatchMethodCallReturnTypeRector`
- class: [`Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchMethodCallReturnTypeRector`](/rules/naming/src/Rector/Foreach_/RenameForeachValueVariableToMatchMethodCallReturnTypeRector.php)
- [test fixtures](/rules/naming/tests/Rector/Foreach_/RenameForeachValueVariableToMatchMethodCallReturnTypeRector/Fixture)
Renames value variable name in foreach loop to match method type
```diff
class SomeClass
{
public function run()
{
$array = [];
- foreach ($object->getMethods() as $property) {
- $array[] = $property;
+ foreach ($object->getMethods() as $method) {
+ $array[] = $method;
}
}
}
```
<br><br>
### `RenameParamToMatchTypeRector`
- class: [`Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector`](/rules/naming/src/Rector/ClassMethod/RenameParamToMatchTypeRector.php)
@ -8884,8 +9035,8 @@ Takes `setExpectedException()` 2nd and next arguments to own methods in PHPUnit.
```diff
-$this->setExpectedException(Exception::class, "Message", "CODE");
+$this->setExpectedException(Exception::class);
+$this->expectExceptionMessage("Message");
+$this->expectExceptionCode("CODE");
+$this->expectExceptionMessage('Message');
+$this->expectExceptionCode('CODE');
```
<br><br>
@ -9146,7 +9297,7 @@ Simplify unnecessary foreach check of instances
```diff
-foreach ($foos as $foo) {
- $this->assertInstanceOf(\SplFileInfo::class, $foo);
- $this->assertInstanceOf(SplFileInfo::class, $foo);
-}
+$this->assertContainsOnlyInstancesOf(\SplFileInfo::class, $foos);
```
@ -10294,12 +10445,14 @@ Changes multi catch of same exception to single one | separated.
```diff
try {
// Some code...
- // Some code...
-} catch (ExceptionType1 $exception) {
- $sameCode;
- $sameCode;
-} catch (ExceptionType2 $exception) {
- $sameCode;
+ // Some code...
+} catch (ExceptionType1 | ExceptionType2 $exception) {
$sameCode;
+ $sameCode;
}
```
@ -11370,13 +11523,14 @@ Change global `$variables` to private properties
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11404,13 +11558,14 @@ Migrate PhpSpec behavior to PHPUnit test
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11438,13 +11593,14 @@ Migrate PhpSpec behavior to PHPUnit test
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11472,13 +11628,14 @@ Migrate PhpSpec behavior to PHPUnit test
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11506,13 +11663,14 @@ Migrate PhpSpec behavior to PHPUnit test
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11540,13 +11698,14 @@ Migrate PhpSpec behavior to PHPUnit test
Migrate PhpSpec behavior to PHPUnit test
```diff
-
namespace spec\SomeNamespaceForThisTest;
-use PhpSpec\ObjectBehavior;
-
class OrderSpec extends ObjectBehavior
{
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod)
- public function let(OrderFactory $factory, ShippingMethod $shippingMethod): void
+ /**
+ * @var \SomeNamespaceForThisTest\Order
+ */
@ -11806,6 +11965,31 @@ Adds a new `$services->set(...)` call to PHP Config
## RemovingStatic
### `LocallyCalledStaticMethodToNonStaticRector`
- class: [`Rector\RemovingStatic\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector`](/rules/removing-static/src/Rector/ClassMethod/LocallyCalledStaticMethodToNonStaticRector.php)
- [test fixtures](/rules/removing-static/tests/Rector/ClassMethod/LocallyCalledStaticMethodToNonStaticRector/Fixture)
Change static method and local-only calls to non-static
```diff
class SomeClass
{
public function run()
{
- self::someStatic();
+ $this->someStatic();
}
- private static function someStatic()
+ private function someStatic()
{
}
}
```
<br><br>
### `NewUniqueObjectToEntityFactoryRector`
- class: [`Rector\RemovingStatic\Rector\Class_\NewUniqueObjectToEntityFactoryRector`](/rules/removing-static/src/Rector/Class_/NewUniqueObjectToEntityFactoryRector.php)
@ -13174,7 +13358,7 @@ Returns int from Command::execute command
class SomeCommand extends Command
{
- public function execute(InputInterface $input, OutputInterface $output)
+ public function index(InputInterface $input, OutputInterface $output): int
+ public function execute(InputInterface $input, OutputInterface $output): int
{
- return null;
+ return 0;

View File

@ -13,11 +13,13 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodReferenceAnalyzer;
use Rector\NodeCollector\ValueObject\ArrayCallable;
use Rector\NodeNameResolver\NodeNameResolver;
@ -26,6 +28,11 @@ use Rector\NodeTypeResolver\NodeTypeResolver;
/**
* All parsed nodes grouped type
* @todo add ParsedNodesRepository, merge with all other node collectors to smymplfiy the access
*
* Have api like:
* - findXByX for N
* - getXByX for 1
*/
final class ParsedFunctionLikeNodeCollector
{
@ -146,6 +153,17 @@ final class ParsedFunctionLikeNodeCollector
return $this->methodsCallsByTypeAndMethod[$className][$methodName] ?? $this->arrayCallablesByTypeAndMethod[$className][$methodName] ?? [];
}
/**
* @return StaticCall[]
*/
public function findStaticCallsByClassMethod(ClassMethod $classMethod): array
{
$calls = $this->findCallsByClassMethod($classMethod);
return array_filter($calls, function (Node $node): bool {
return $node instanceof StaticCall;
});
}
/**
* @return ClassMethod[]
*/
@ -168,6 +186,28 @@ final class ParsedFunctionLikeNodeCollector
return $classMethods;
}
public function findClassMethodByStaticCall(StaticCall $staticCall): ?ClassMethod
{
$staticCallType = $this->nodeTypeResolver->resolve($staticCall->class);
if ($staticCallType instanceof TypeWithClassName) {
$staticCallClass = $staticCallType->getClassName();
} else {
// possible union type?
return null;
}
if ($staticCallClass === null) {
return null;
}
$method = $this->nodeNameResolver->getName($staticCall->name);
if ($method === null) {
return null;
}
return $this->findMethod($staticCallClass, $method);
}
public function findMethod(string $className, string $methodName): ?ClassMethod
{
if (isset($this->classMethodsByType[$className][$methodName])) {
@ -201,6 +241,15 @@ final class ParsedFunctionLikeNodeCollector
});
}
public function findClassMethodByMethodReflection(MethodReflection $methodReflection): ?ClassMethod
{
$methodName = $methodReflection->getName();
/** @var string $className */
$className = $methodReflection->getDeclaringClass()->getName();
return $this->findMethod($className, $methodName);
}
private function addMethod(ClassMethod $classMethod): void
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
@ -239,6 +288,21 @@ final class ParsedFunctionLikeNodeCollector
$this->addCallByType($node, $classType, $methodName);
}
/**
* @return MethodCall[]|StaticCall[]|ArrayCallable[]
*/
private function findCallsByClassMethod(ClassMethod $classMethod): array
{
$class = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
if (! is_string($class)) {
throw new ShouldNotHappenException();
}
/** @var string $method */
$method = $this->nodeNameResolver->getName($classMethod->name);
return $this->findByClassAndMethod($class, $method);
}
private function resolveNodeClassTypes(Node $node): Type
{
if ($node instanceof MethodCall && $node->var instanceof Variable && $node->var->name === 'this') {

View File

@ -49,7 +49,9 @@ final class ParentClassMethodTypeOverrideGuard
return true;
}
$parentClassMethod = $this->getClassMethodByMethodReflection($parentClassMethodReflection);
$parentClassMethod = $this->parsedFunctionLikeNodeCollector->findClassMethodByMethodReflection(
$parentClassMethodReflection
);
// if null, we're unable to override → skip it
return $parentClassMethod !== null;
@ -84,14 +86,4 @@ final class ParentClassMethodTypeOverrideGuard
return null;
}
private function getClassMethodByMethodReflection(MethodReflection $parentClassMethodReflection): ?ClassMethod
{
$methodName = $parentClassMethodReflection->getName();
/** @var string $className */
$className = $parentClassMethodReflection->getDeclaringClass()->getName();
return $this->parsedFunctionLikeNodeCollector->findMethod($className, $methodName);
}
}

View File

@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace Rector\RemovingStatic\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeCollector\NodeCollector\ParsedFunctionLikeNodeCollector;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\LocallyCalledStaticMethodToNonStaticRectorTest
*/
final class LocallyCalledStaticMethodToNonStaticRector extends AbstractRector
{
/**
* @var ParsedFunctionLikeNodeCollector
*/
private $parsedFunctionLikeNodeCollector;
public function __construct(ParsedFunctionLikeNodeCollector $parsedFunctionLikeNodeCollector)
{
$this->parsedFunctionLikeNodeCollector = $parsedFunctionLikeNodeCollector;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Change static method and local-only calls to non-static', [
new CodeSample(
<<<'PHP'
class SomeClass
{
public function run()
{
self::someStatic();
}
private static function someStatic()
{
}
}
PHP
,
<<<'PHP'
class SomeClass
{
public function run()
{
$this->someStatic();
}
private function someStatic()
{
}
}
PHP
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [ClassMethod::class, StaticCall::class];
}
/**
* @param ClassMethod|StaticCall $node
*/
public function refactor(Node $node): ?Node
{
if ($node instanceof ClassMethod) {
return $this->refactorClassMethod($node);
}
return $this->refactorStaticCall($node);
}
private function refactorClassMethod(ClassMethod $classMethod): ?ClassMethod
{
if (! $classMethod->isStatic()) {
return null;
}
if (! $this->isClassMethodWithOnlyLocalStaticCalls($classMethod)) {
return null;
}
// change static calls to non-static ones, but only if in non-static method!!!
$this->makeNonStatic($classMethod);
return $classMethod;
}
private function refactorStaticCall(StaticCall $staticCall): ?MethodCall
{
$classMethod = $this->parsedFunctionLikeNodeCollector->findClassMethodByStaticCall($staticCall);
if ($classMethod === null) {
return null;
}
// is static call in the same as class method
if (! $this->haveSharedClass($classMethod, [$staticCall])) {
return null;
}
$thisVariable = new Variable('this');
return new MethodCall($thisVariable, $staticCall->name, $staticCall->args);
}
private function isClassMethodWithOnlyLocalStaticCalls(ClassMethod $classMethod): bool
{
$staticCalls = $this->parsedFunctionLikeNodeCollector->findStaticCallsByClassMethod($classMethod);
// get static staticCalls
return $this->haveSharedClass($classMethod, $staticCalls);
}
/**
* @param Node[] $nodes
*/
private function haveSharedClass(Node $mainNode, array $nodes): bool
{
$mainNodeClass = $mainNode->getAttribute(AttributeKey::CLASS_NAME);
foreach ($nodes as $node) {
$nodeClass = $node->getAttribute(AttributeKey::CLASS_NAME);
if ($mainNodeClass !== $nodeClass) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\Fixture;
class DoubleStaticMethod
{
public static function run()
{
self::someStatic();
}
private static function someStatic()
{
}
}
?>
-----
<?php
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\Fixture;
class DoubleStaticMethod
{
public function run()
{
$this->someStatic();
}
private function someStatic()
{
}
}
?>

View File

@ -0,0 +1,35 @@
<?php
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\Fixture;
class SomeClass
{
public function run()
{
self::someStatic();
}
private static function someStatic()
{
}
}
?>
-----
<?php
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\Fixture;
class SomeClass
{
public function run()
{
$this->someStatic();
}
private function someStatic()
{
}
}
?>

View File

@ -0,0 +1,18 @@
<?php
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector\Fixture;
class SkipElseClass
{
public function run()
{
AnotherClass::someStatic();
}
}
class AnotherClass
{
public static function someStatic()
{
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Rector\RemovingStatic\Tests\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\RemovingStatic\Rector\ClassMethod\LocallyCalledStaticMethodToNonStaticRector;
use Symplify\SmartFileSystem\SmartFileInfo;
final class LocallyCalledStaticMethodToNonStaticRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return LocallyCalledStaticMethodToNonStaticRector::class;
}
}

View File

@ -49,6 +49,14 @@ final class VisibilityManipulator
$this->addVisibilityFlag($node, self::ABSTRACT);
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makeNonStatic(Node $node): void
{
$node->flags -= Class_::MODIFIER_STATIC;
}
/**
* @param Class_|ClassMethod $node
*/

View File

@ -94,6 +94,14 @@ trait VisibilityTrait
$this->visibilityManipulator->makeStatic($node);
}
/**
* @param ClassMethod|Property|ClassConst $node
*/
public function makeNonStatic(Node $node): void
{
$this->visibilityManipulator->makeNonStatic($node);
}
public function makeFinal(Class_ $class): void
{
$this->visibilityManipulator->makeFinal($class);