Updated Rector to commit 21c9e59aaaae15e1baac98b80b6d3e3be5c5d88d

21c9e59aaa Adapt PrivateConstantToSelfRector to work on non-final classes, too (#3198)
This commit is contained in:
Tomas Votruba 2022-12-17 08:33:16 +00:00
parent c9d5c64791
commit 33551cbeec
6 changed files with 140 additions and 34 deletions

View File

@ -1,4 +1,4 @@
# 412 Rules Overview
# 413 Rules Overview
<br>
@ -48,7 +48,7 @@
- [Php81](#php81) (11)
- [Php82](#php82) (1)
- [Php82](#php82) (2)
- [Privatization](#privatization) (8)
@ -596,10 +596,25 @@ Change multiple null compares to ?? queue
### ConvertStaticPrivateConstantToSelfRector
Replaces static::* access to private constants with self::* on final classes
Replaces static::* access to private constants with self::*
:wrench: **configure it!**
- class: [`Rector\CodeQuality\Rector\ClassConstFetch\ConvertStaticPrivateConstantToSelfRector`](../rules/CodeQuality/Rector/ClassConstFetch/ConvertStaticPrivateConstantToSelfRector.php)
```php
use Rector\CodeQuality\Rector\ClassConstFetch\ConvertStaticPrivateConstantToSelfRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(ConvertStaticPrivateConstantToSelfRector::class, [
ConvertStaticPrivateConstantToSelfRector::ENABLE_FOR_NON_FINAL_CLASSES => false,
]);
};
```
```diff
final class Foo {
private const BAR = 'bar';
@ -6511,6 +6526,21 @@ Decorate read-only class with `readonly` attribute
<br>
### Utf8DecodeEncodeToMbConvertEncodingRector
Change deprecated utf8_decode and utf8_encode to mb_convert_encoding
- class: [`Rector\Php82\Rector\FuncCall\Utf8DecodeEncodeToMbConvertEncodingRector`](../rules/Php82/Rector/FuncCall/Utf8DecodeEncodeToMbConvertEncodingRector.php)
```diff
-utf8_decode($value);
-utf8_encode($value);
+mb_convert_encoding($value, 'ISO-8859-1');
+mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1');
```
<br>
## Privatization
### ChangeGlobalVariablesToPropertiesRector

View File

@ -8,19 +8,47 @@ use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Reflection\ClassReflection;
use Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\CodeQuality\Rector\ClassConstFetch\ConvertStaticPrivateConstantToSelfRector\ConvertStaticPrivateConstantToSelfRectorTest
* @see https://3v4l.org/8Y0ba
* @see https://phpstan.org/r/11d4c850-1a40-4fae-b665-291f96104d11
*/
final class ConvertStaticPrivateConstantToSelfRector extends AbstractRector
final class ConvertStaticPrivateConstantToSelfRector extends AbstractRector implements AllowEmptyConfigurableRectorInterface
{
/**
* @api
* @var string
*/
public const ENABLE_FOR_NON_FINAL_CLASSES = 'enable_for_non_final_classes';
/**
* @var bool
*/
private $enableForNonFinalClasses = \false;
/**
* @readonly
* @var \Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer
*/
private $familyRelationsAnalyzer;
/**
* @readonly
* @var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver;
public function __construct(FamilyRelationsAnalyzer $familyRelationsAnalyzer, ReflectionResolver $reflectionResolver)
{
$this->familyRelationsAnalyzer = $familyRelationsAnalyzer;
$this->reflectionResolver = $reflectionResolver;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Replaces static::* access to private constants with self::* on final classes', [new CodeSample(<<<'CODE_SAMPLE'
return new RuleDefinition('Replaces static::* access to private constants with self::*', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
final class Foo {
private const BAR = 'bar';
public function run()
@ -38,21 +66,26 @@ final class Foo {
}
}
CODE_SAMPLE
)]);
, [self::ENABLE_FOR_NON_FINAL_CLASSES => \false])]);
}
public function getNodeTypes() : array
{
return [ClassConstFetch::class];
}
public function configure(array $configuration) : void
{
$this->enableForNonFinalClasses = $configuration[self::ENABLE_FOR_NON_FINAL_CLASSES] ?? (bool) \current($configuration);
}
/**
* @param ClassConstFetch $node
*/
public function refactor(Node $node) : ?ClassConstFetch
{
if (!$this->isUsingStatic($node)) {
$class = $this->betterNodeFinder->findParentType($node, Class_::class);
if (!$class instanceof Class_) {
return null;
}
if (!$this->isPrivateConstant($node)) {
if ($this->shouldBeSkipped($class, $node)) {
return null;
}
$node->class = new Name('self');
@ -65,25 +98,68 @@ CODE_SAMPLE
}
return $classConstFetch->class->toString() === 'static';
}
private function isPrivateConstant(ClassConstFetch $classConstFetch) : bool
private function isPrivateConstant(ClassConstFetch $constant, Class_ $class) : bool
{
$class = $this->betterNodeFinder->findParentType($classConstFetch, Class_::class);
if (!$class instanceof Class_) {
return \false;
}
if (!$class->isFinal()) {
return \false;
}
$constantName = $classConstFetch->name;
if (!$constantName instanceof Identifier) {
$constantName = $this->getConstantName($constant);
if ($constantName === null) {
return \false;
}
foreach ($class->getConstants() as $classConst) {
if (!$this->nodeNameResolver->isName($classConst, $constantName->toString())) {
if (!$this->nodeNameResolver->isName($classConst, $constantName)) {
continue;
}
return $classConst->isPrivate();
}
return \false;
}
private function isUsedInPrivateMethod(ClassConstFetch $node) : bool
{
$method = $this->betterNodeFinder->findParentType($node, Node\Stmt\ClassMethod::class);
if (!$method instanceof Node\Stmt\ClassMethod) {
return \false;
}
return $method->flags === Class_::MODIFIER_PRIVATE;
}
private function shouldBeSkipped(Class_ $class, ClassConstFetch $classConstFetch) : bool
{
if (!$this->isUsingStatic($classConstFetch)) {
return \true;
}
if (!$this->isPrivateConstant($classConstFetch, $class)) {
return \true;
}
if ($this->isUsedInPrivateMethod($classConstFetch)) {
return \false;
}
if ($this->enableForNonFinalClasses) {
return $this->isOverwrittenInChildClass($classConstFetch);
}
return !$class->isFinal();
}
private function isOverwrittenInChildClass(ClassConstFetch $classConstFetch) : bool
{
$constantName = $this->getConstantName($classConstFetch);
if ($constantName === null) {
return \false;
}
$classReflection = $this->reflectionResolver->resolveClassReflection($classConstFetch);
if (!$classReflection instanceof ClassReflection) {
return \false;
}
$childrenClassReflections = $this->familyRelationsAnalyzer->getChildrenOfClassReflection($classReflection);
foreach ($childrenClassReflections as $childrenClassReflection) {
if ($childrenClassReflection->hasConstant($constantName)) {
return \true;
}
}
return \false;
}
private function getConstantName(ClassConstFetch $classConstFetch) : ?string
{
$constantNameIdentifier = $classConstFetch->name;
if (!$constantNameIdentifier instanceof Identifier) {
return null;
}
return $constantNameIdentifier->toString();
}
}

View File

@ -17,12 +17,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '14e60b06039ff4af2e8d4670390fdcf8c66f5cbe';
public const PACKAGE_VERSION = '21c9e59aaaae15e1baac98b80b6d3e3be5c5d88d';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2022-12-17 09:28:50';
public const RELEASE_DATE = '2022-12-17 09:29:16';
/**
* @var int
*/

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b::getLoader();
return ComposerAutoloaderInit86de0d5c87da90d3143aeb13739f358e::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b
class ComposerAutoloaderInit86de0d5c87da90d3143aeb13739f358e
{
private static $loader;
@ -22,19 +22,19 @@ class ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit86de0d5c87da90d3143aeb13739f358e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit86de0d5c87da90d3143aeb13739f358e', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit1e073b5cc27535a793f501c33ad1391b::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit86de0d5c87da90d3143aeb13739f358e::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInit1e073b5cc27535a793f501c33ad1391b::$files;
$includeFiles = \Composer\Autoload\ComposerStaticInit86de0d5c87da90d3143aeb13739f358e::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire1e073b5cc27535a793f501c33ad1391b($fileIdentifier, $file);
composerRequire86de0d5c87da90d3143aeb13739f358e($fileIdentifier, $file);
}
return $loader;
@ -46,7 +46,7 @@ class ComposerAutoloaderInit1e073b5cc27535a793f501c33ad1391b
* @param string $file
* @return void
*/
function composerRequire1e073b5cc27535a793f501c33ad1391b($fileIdentifier, $file)
function composerRequire86de0d5c87da90d3143aeb13739f358e($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit1e073b5cc27535a793f501c33ad1391b
class ComposerStaticInit86de0d5c87da90d3143aeb13739f358e
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -3054,9 +3054,9 @@ class ComposerStaticInit1e073b5cc27535a793f501c33ad1391b
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit1e073b5cc27535a793f501c33ad1391b::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit1e073b5cc27535a793f501c33ad1391b::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit1e073b5cc27535a793f501c33ad1391b::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit86de0d5c87da90d3143aeb13739f358e::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit86de0d5c87da90d3143aeb13739f358e::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit86de0d5c87da90d3143aeb13739f358e::$classMap;
}, null, ClassLoader::class);
}