2019-10-13 05:59:52 +00:00
< ? php
2021-05-09 20:15:43 +00:00
declare ( strict_types = 1 );
2019-09-22 18:57:03 +00:00
namespace Rector\Php70\Rector\MethodCall ;
2018-12-31 17:39:36 +00:00
use PhpParser\Node ;
use PhpParser\Node\Expr\MethodCall ;
2021-03-19 23:11:36 +00:00
use PhpParser\Node\Expr\Variable ;
2021-01-24 20:12:02 +00:00
use PhpParser\Node\Stmt\Class_ ;
2021-11-07 04:15:35 +00:00
use PhpParser\Node\Stmt\ClassLike ;
2021-02-28 07:47:48 +00:00
use PHPStan\Reflection\Php\PhpMethodReflection ;
2021-02-27 00:58:09 +00:00
use PHPStan\Type\ObjectType ;
2021-10-25 13:44:53 +00:00
use Rector\Core\Enum\ObjectReference ;
2020-02-06 21:48:18 +00:00
use Rector\Core\Rector\AbstractRector ;
2021-06-26 11:50:38 +00:00
use Rector\Core\Reflection\ReflectionResolver ;
2021-09-24 14:11:08 +00:00
use Rector\Core\ValueObject\PhpVersionFeature ;
2020-03-28 23:06:05 +00:00
use Rector\NodeCollector\StaticAnalyzer ;
2021-09-24 14:11:08 +00:00
use Rector\VersionBonding\Contract\MinPhpVersionInterface ;
2020-11-16 17:50:38 +00:00
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample ;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition ;
2018-12-31 17:39:36 +00:00
/**
2022-05-12 19:17:07 +00:00
* @ changelog https :// 3 v4l . org / rkiSC
2021-03-12 22:20:25 +00:00
* @ see \Rector\Tests\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector\ThisCallOnStaticMethodToStaticCallRectorTest
2018-12-31 17:39:36 +00:00
*/
2022-05-27 11:51:31 +00:00
final class ThisCallOnStaticMethodToStaticCallRector extends \Rector\Core\Rector\AbstractRector implements \Rector\VersionBonding\Contract\MinPhpVersionInterface
2018-12-31 17:39:36 +00:00
{
2020-03-28 23:06:05 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-05-10 23:39:21 +00:00
* @ var \Rector\NodeCollector\StaticAnalyzer
2020-03-28 23:06:05 +00:00
*/
private $staticAnalyzer ;
2021-06-26 11:50:38 +00:00
/**
2021-12-04 12:47:17 +00:00
* @ readonly
2021-06-26 11:50:38 +00:00
* @ var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver ;
2022-05-27 11:51:31 +00:00
public function __construct ( \Rector\NodeCollector\StaticAnalyzer $staticAnalyzer , \Rector\Core\Reflection\ReflectionResolver $reflectionResolver )
2020-03-28 23:06:05 +00:00
{
$this -> staticAnalyzer = $staticAnalyzer ;
2021-06-26 11:50:38 +00:00
$this -> reflectionResolver = $reflectionResolver ;
2020-03-28 23:06:05 +00:00
}
2021-09-24 14:11:08 +00:00
public function provideMinPhpVersion () : int
{
2022-05-27 11:51:31 +00:00
return \Rector\Core\ValueObject\PhpVersionFeature :: STATIC_CALL_ON_NON_STATIC ;
2021-09-24 14:11:08 +00:00
}
2022-05-27 11:51:31 +00:00
public function getRuleDefinition () : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
2018-12-31 17:39:36 +00:00
{
2022-05-27 11:51:31 +00:00
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition ( 'Changes $this->call() to static method to static call' , [ new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample ( <<< 'CODE_SAMPLE'
2018-12-31 17:39:36 +00:00
class SomeClass
{
public static function run ()
{
$this -> eat ();
}
public static function eat ()
{
}
}
2020-09-15 08:23:13 +00:00
CODE_SAMPLE
2021-05-09 20:15:43 +00:00
, <<< 'CODE_SAMPLE'
2018-12-31 17:39:36 +00:00
class SomeClass
{
public static function run ()
{
2020-06-19 13:09:46 +00:00
static :: eat ();
2018-12-31 17:39:36 +00:00
}
public static function eat ()
{
}
}
2020-09-15 08:23:13 +00:00
CODE_SAMPLE
2021-05-09 20:15:43 +00:00
)]);
2018-12-31 17:39:36 +00:00
}
/**
2021-02-27 00:06:15 +00:00
* @ return array < class - string < Node >>
2018-12-31 17:39:36 +00:00
*/
2021-05-09 20:15:43 +00:00
public function getNodeTypes () : array
2018-12-31 17:39:36 +00:00
{
2022-05-27 11:51:31 +00:00
return [ \PhpParser\Node\Expr\MethodCall :: class ];
2018-12-31 17:39:36 +00:00
}
/**
2021-12-10 10:22:23 +00:00
* @ param MethodCall $node
2018-12-31 17:39:36 +00:00
*/
2022-05-27 11:51:31 +00:00
public function refactor ( \PhpParser\Node $node ) : ? \PhpParser\Node
2018-12-31 17:39:36 +00:00
{
2022-05-27 11:51:31 +00:00
if ( ! $node -> var instanceof \PhpParser\Node\Expr\Variable ) {
2021-03-19 23:11:36 +00:00
return null ;
}
2021-05-09 20:15:43 +00:00
if ( ! $this -> nodeNameResolver -> isName ( $node -> var , 'this' )) {
2018-12-31 17:39:36 +00:00
return null ;
}
2021-01-24 20:12:02 +00:00
$methodName = $this -> getName ( $node -> name );
if ( $methodName === null ) {
return null ;
}
2020-06-21 10:08:41 +00:00
// skip PHPUnit calls, as they accept both self:: and $this-> formats
2022-05-27 11:51:31 +00:00
if ( $this -> isObjectType ( $node -> var , new \PHPStan\Type\ObjectType ( 'PHPUnit\\Framework\\TestCase' ))) {
2019-11-23 20:12:57 +00:00
return null ;
2019-11-08 15:48:05 +00:00
}
2022-05-27 11:51:31 +00:00
$classLike = $this -> betterNodeFinder -> findParentType ( $node , \PhpParser\Node\Stmt\ClassLike :: class );
if ( ! $classLike instanceof \PhpParser\Node\Stmt\ClassLike ) {
2019-01-25 14:32:42 +00:00
return null ;
}
2021-11-09 13:36:07 +00:00
$className = ( string ) $this -> nodeNameResolver -> getName ( $classLike );
2020-03-28 23:06:05 +00:00
$isStaticMethod = $this -> staticAnalyzer -> isStaticMethod ( $methodName , $className );
2021-05-09 20:15:43 +00:00
if ( ! $isStaticMethod ) {
2018-12-31 17:39:36 +00:00
return null ;
}
2021-10-25 13:44:53 +00:00
$objectReference = $this -> resolveClassSelf ( $node );
return $this -> nodeFactory -> createStaticCall ( $objectReference , $methodName , $node -> args );
2021-01-24 20:12:02 +00:00
}
2022-05-27 11:51:31 +00:00
private function resolveClassSelf ( \PhpParser\Node\Expr\MethodCall $methodCall ) : \Rector\Core\Enum\ObjectReference
2021-01-24 20:12:02 +00:00
{
2022-05-27 11:51:31 +00:00
$classLike = $this -> betterNodeFinder -> findParentType ( $methodCall , \PhpParser\Node\Stmt\Class_ :: class );
if ( ! $classLike instanceof \PhpParser\Node\Stmt\Class_ ) {
return \Rector\Core\Enum\ObjectReference :: STATIC ();
2021-01-24 20:12:02 +00:00
}
if ( $classLike -> isFinal ()) {
2022-05-27 11:51:31 +00:00
return \Rector\Core\Enum\ObjectReference :: SELF ();
2021-01-24 20:12:02 +00:00
}
2021-06-26 11:50:38 +00:00
$methodReflection = $this -> reflectionResolver -> resolveMethodReflectionFromMethodCall ( $methodCall );
2022-05-27 11:51:31 +00:00
if ( ! $methodReflection instanceof \PHPStan\Reflection\Php\PhpMethodReflection ) {
return \Rector\Core\Enum\ObjectReference :: STATIC ();
2021-01-24 20:12:02 +00:00
}
2021-05-09 20:15:43 +00:00
if ( ! $methodReflection -> isPrivate ()) {
2022-05-27 11:51:31 +00:00
return \Rector\Core\Enum\ObjectReference :: STATIC ();
2021-02-21 09:32:45 +00:00
}
2022-05-27 11:51:31 +00:00
return \Rector\Core\Enum\ObjectReference :: SELF ();
2018-12-31 17:39:36 +00:00
}
}