Updated Rector to commit 493e4f89c9f9a033668301cd4eee4df7e77df0cb

493e4f89c9 Skip code changes on unresolvable/unknown classes (#4619)
This commit is contained in:
Tomas Votruba 2023-08-07 10:55:35 +00:00
parent 60a90b19ce
commit 4cf14d6438
15 changed files with 79 additions and 25 deletions

View File

@ -0,0 +1,8 @@
<?php
declare (strict_types=1);
namespace Rector\VendorLocker\Exception;
final class UnresolvableClassException extends \Exception
{
}

View File

@ -7,10 +7,13 @@ use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\Type; use PHPStan\Type\Type;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Reflection\ReflectionResolver; use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\Util\Reflection\PrivatesAccessor;
use Rector\NodeNameResolver\NodeNameResolver; use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\TypeComparator\TypeComparator; use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
use Rector\StaticTypeMapper\StaticTypeMapper; use Rector\StaticTypeMapper\StaticTypeMapper;
use Rector\VendorLocker\Exception\UnresolvableClassException;
final class ParentClassMethodTypeOverrideGuard final class ParentClassMethodTypeOverrideGuard
{ {
/** /**
@ -33,31 +36,62 @@ final class ParentClassMethodTypeOverrideGuard
* @var \Rector\StaticTypeMapper\StaticTypeMapper * @var \Rector\StaticTypeMapper\StaticTypeMapper
*/ */
private $staticTypeMapper; private $staticTypeMapper;
public function __construct(NodeNameResolver $nodeNameResolver, ReflectionResolver $reflectionResolver, TypeComparator $typeComparator, StaticTypeMapper $staticTypeMapper) /**
* @readonly
* @var \Rector\Core\Util\Reflection\PrivatesAccessor
*/
private $privatesAccessor;
public function __construct(NodeNameResolver $nodeNameResolver, ReflectionResolver $reflectionResolver, TypeComparator $typeComparator, StaticTypeMapper $staticTypeMapper, PrivatesAccessor $privatesAccessor)
{ {
$this->nodeNameResolver = $nodeNameResolver; $this->nodeNameResolver = $nodeNameResolver;
$this->reflectionResolver = $reflectionResolver; $this->reflectionResolver = $reflectionResolver;
$this->typeComparator = $typeComparator; $this->typeComparator = $typeComparator;
$this->staticTypeMapper = $staticTypeMapper; $this->staticTypeMapper = $staticTypeMapper;
$this->privatesAccessor = $privatesAccessor;
} }
public function hasParentClassMethod(ClassMethod $classMethod) : bool public function hasParentClassMethod(ClassMethod $classMethod) : ?bool
{ {
return $this->getParentClassMethod($classMethod) instanceof MethodReflection; try {
$parentClassMethod = $this->resolveParentClassMethod($classMethod);
return $parentClassMethod instanceof MethodReflection;
} catch (UnresolvableClassException $exception) {
// we don't know all involved parents.
return null;
}
} }
public function getParentClassMethod(ClassMethod $classMethod) : ?MethodReflection public function getParentClassMethod(ClassMethod $classMethod) : ?MethodReflection
{
try {
$parentClassMethod = $this->resolveParentClassMethod($classMethod);
return $parentClassMethod;
} catch (UnresolvableClassException $exception) {
// we don't know all involved parents.
throw new ShouldNotHappenException('Unable to resolve involved class. You are likely missing hasParentClassMethod() before calling getParentClassMethod().');
}
}
/**
* @throws UnresolvableClassException
*/
private function resolveParentClassMethod(ClassMethod $classMethod) : ?MethodReflection
{ {
$classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod);
if (!$classReflection instanceof ClassReflection) { if (!$classReflection instanceof ClassReflection) {
return null; // we can't resolve the class, so we don't know.
throw new UnresolvableClassException();
} }
/** @var string $methodName */ /** @var string $methodName */
$methodName = $this->nodeNameResolver->getName($classMethod); $methodName = $this->nodeNameResolver->getName($classMethod);
$parentClassReflection = $classReflection->getParentClass(); $currentClassReflection = $classReflection;
while ($parentClassReflection instanceof ClassReflection) { while ($this->hasClassParent($currentClassReflection)) {
$parentClassReflection = $currentClassReflection->getParentClass();
if (!$parentClassReflection instanceof ClassReflection) {
// per AST we have a parent class, but our reflection classes are not able to load its class definition/signature
throw new UnresolvableClassException();
}
if ($parentClassReflection->hasNativeMethod($methodName)) { if ($parentClassReflection->hasNativeMethod($methodName)) {
return $parentClassReflection->getNativeMethod($methodName); return $parentClassReflection->getNativeMethod($methodName);
} }
$parentClassReflection = $parentClassReflection->getParentClass(); $currentClassReflection = $parentClassReflection;
} }
foreach ($classReflection->getInterfaces() as $interfaceReflection) { foreach ($classReflection->getInterfaces() as $interfaceReflection) {
if (!$interfaceReflection->hasNativeMethod($methodName)) { if (!$interfaceReflection->hasNativeMethod($methodName)) {
@ -67,6 +101,14 @@ final class ParentClassMethodTypeOverrideGuard
} }
return null; return null;
} }
private function hasClassParent(ClassReflection $classReflection) : bool
{
// XXX rework this hack, after https://github.com/phpstan/phpstan-src/pull/2563 landed
$nativeReflection = $classReflection->getNativeReflection();
$betterReflectionClass = $this->privatesAccessor->getPrivateProperty($nativeReflection, 'betterReflectionClass');
$parentClassName = $this->privatesAccessor->getPrivateProperty($betterReflectionClass, 'parentClassName');
return $parentClassName !== null;
}
public function shouldSkipReturnTypeChange(ClassMethod $classMethod, Type $parentType) : bool public function shouldSkipReturnTypeChange(ClassMethod $classMethod, Type $parentType) : bool
{ {
if ($classMethod->returnType === null) { if ($classMethod->returnType === null) {

View File

@ -72,6 +72,7 @@ final class ParentPropertyLookupGuard
if ($this->propertyManipulator->isUsedByTrait($classReflection, $propertyName)) { if ($this->propertyManipulator->isUsedByTrait($classReflection, $propertyName)) {
return \false; return \false;
} }
// XXX rework this hack, after https://github.com/phpstan/phpstan-src/pull/2563 landed
$nativeReflection = $classReflection->getNativeReflection(); $nativeReflection = $classReflection->getNativeReflection();
$betterReflectionClass = $this->privatesAccessor->getPrivateProperty($nativeReflection, 'betterReflectionClass'); $betterReflectionClass = $this->privatesAccessor->getPrivateProperty($nativeReflection, 'betterReflectionClass');
$parentClassName = $this->privatesAccessor->getPrivateProperty($betterReflectionClass, 'parentClassName'); $parentClassName = $this->privatesAccessor->getPrivateProperty($betterReflectionClass, 'parentClassName');

View File

@ -121,7 +121,7 @@ CODE_SAMPLE
if (!$paramType instanceof Node) { if (!$paramType instanceof Node) {
continue; continue;
} }
if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node)) { if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node) !== \false) {
return null; return null;
} }
$param->type = $paramType; $param->type = $paramType;

View File

@ -135,7 +135,7 @@ CODE_SAMPLE
if ($classMethod->params === []) { if ($classMethod->params === []) {
return \true; return \true;
} }
return $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod); return $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod) !== \false;
} }
/** /**
* @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\NullableType|\PhpParser\Node\UnionType|\PhpParser\Node\ComplexType $paramType * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name|\PhpParser\Node\NullableType|\PhpParser\Node\UnionType|\PhpParser\Node\ComplexType $paramType

View File

@ -177,7 +177,7 @@ CODE_SAMPLE
return \true; return \true;
} }
if ($node instanceof ClassMethod) { if ($node instanceof ClassMethod) {
if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node)) { if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node) !== \false) {
return \true; return \true;
} }
if ($node->isMagic()) { if ($node->isMagic()) {

View File

@ -70,7 +70,7 @@ CODE_SAMPLE
public function refactor(Node $node) : ?Node public function refactor(Node $node) : ?Node
{ {
$hasChanged = \false; $hasChanged = \false;
if ($node instanceof ClassMethod && $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node)) { if ($node instanceof ClassMethod && $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node) !== \false) {
return null; return null;
} }
foreach ($node->getParams() as $param) { foreach ($node->getParams() as $param) {

View File

@ -71,7 +71,7 @@ CODE_SAMPLE
*/ */
public function refactor(Node $node) : ?Node public function refactor(Node $node) : ?Node
{ {
if ($node instanceof ClassMethod && $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node)) { if ($node instanceof ClassMethod && $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node) !== \false) {
return null; return null;
} }
$hasChanged = \false; $hasChanged = \false;

View File

@ -108,7 +108,7 @@ CODE_SAMPLE
if ($classMethod->isAbstract()) { if ($classMethod->isAbstract()) {
return null; return null;
} }
if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod)) { if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod) !== \false) {
return null; return null;
} }
$originalParamType = $this->resolveParamOriginalType($param, $scope); $originalParamType = $this->resolveParamOriginalType($param, $scope);

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api * @api
* @var string * @var string
*/ */
public const PACKAGE_VERSION = '73112a253e40199adda14259717e4d8c630c97d1'; public const PACKAGE_VERSION = '493e4f89c9f9a033668301cd4eee4df7e77df0cb';
/** /**
* @api * @api
* @var string * @var string
*/ */
public const RELEASE_DATE = '2023-08-07 16:58:34'; public const RELEASE_DATE = '2023-08-07 17:52:00';
/** /**
* @var int * @var int
*/ */

View File

@ -311,6 +311,7 @@ final class ValueResolver
if (!$classReflection->isClass()) { if (!$classReflection->isClass()) {
throw new ShouldNotHappenException('Complete class parent node for to class const fetch, so "parent" references is resolvable to lookup parent class'); throw new ShouldNotHappenException('Complete class parent node for to class const fetch, so "parent" references is resolvable to lookup parent class');
} }
// XXX rework this hack, after https://github.com/phpstan/phpstan-src/pull/2563 landed
// ensure parent class name still resolved even not autoloaded // ensure parent class name still resolved even not autoloaded
$nativeReflection = $classReflection->getNativeReflection(); $nativeReflection = $classReflection->getNativeReflection();
$betterReflectionClass = $this->privatesAccessor->getPrivateProperty($nativeReflection, 'betterReflectionClass'); $betterReflectionClass = $this->privatesAccessor->getPrivateProperty($nativeReflection, 'betterReflectionClass');

2
vendor/autoload.php vendored
View File

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

View File

@ -2725,6 +2725,7 @@ return array(
'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => $baseDir . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php', 'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => $baseDir . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php',
'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => $baseDir . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php', 'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => $baseDir . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php',
'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => $vendorDir . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php', 'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => $vendorDir . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php',
'Rector\\VendorLocker\\Exception\\UnresolvableClassException' => $baseDir . '/packages/VendorLocker/Exception/UnresolvableClassException.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnVendorLockResolver' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnVendorLockResolver' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnVendorLockResolver.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderIniteb2977d07722edfb3f92b84a842954d4 class ComposerAutoloaderInitd60879e03e03619f65217abab90852fe
{ {
private static $loader; private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderIniteb2977d07722edfb3f92b84a842954d4
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderIniteb2977d07722edfb3f92b84a842954d4', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInitd60879e03e03619f65217abab90852fe', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderIniteb2977d07722edfb3f92b84a842954d4', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInitd60879e03e03619f65217abab90852fe', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php'; require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticIniteb2977d07722edfb3f92b84a842954d4::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInitd60879e03e03619f65217abab90852fe::getInitializer($loader));
$loader->setClassMapAuthoritative(true); $loader->setClassMapAuthoritative(true);
$loader->register(true); $loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticIniteb2977d07722edfb3f92b84a842954d4::$files; $filesToLoad = \Composer\Autoload\ComposerStaticInitd60879e03e03619f65217abab90852fe::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) { $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticIniteb2977d07722edfb3f92b84a842954d4 class ComposerStaticInitd60879e03e03619f65217abab90852fe
{ {
public static $files = array ( public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -2979,6 +2979,7 @@ class ComposerStaticIniteb2977d07722edfb3f92b84a842954d4
'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php', 'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php',
'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php', 'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php',
'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php', 'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php',
'Rector\\VendorLocker\\Exception\\UnresolvableClassException' => __DIR__ . '/../..' . '/packages/VendorLocker/Exception/UnresolvableClassException.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php',
'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnVendorLockResolver' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnVendorLockResolver' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnVendorLockResolver.php',
@ -3010,9 +3011,9 @@ class ComposerStaticIniteb2977d07722edfb3f92b84a842954d4
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticIniteb2977d07722edfb3f92b84a842954d4::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInitd60879e03e03619f65217abab90852fe::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticIniteb2977d07722edfb3f92b84a842954d4::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitd60879e03e03619f65217abab90852fe::$prefixDirsPsr4;
$loader->classMap = ComposerStaticIniteb2977d07722edfb3f92b84a842954d4::$classMap; $loader->classMap = ComposerStaticInitd60879e03e03619f65217abab90852fe::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }