Updated Rector to commit f7e1b1f57e8746e07627799b5d9813e12c1c7b56

f7e1b1f57e [NodeAnalyzer] Use PHPStan ClassReflection to detect anonymous class on ClassAnalyzer (#3543)
This commit is contained in:
Tomas Votruba 2023-03-31 21:41:53 +00:00
parent 817a8ccc28
commit 0e412b55cb
12 changed files with 63 additions and 84 deletions

View File

@ -12,11 +12,11 @@ use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Namespace_;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\CodingStyle\NodeAnalyzer\UseImportNameMatcher;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\Util\StringUtils;
use Rector\Core\ValueObject\Application\File;
@ -69,19 +69,13 @@ final class ShortNameResolver
* @var \Rector\CodingStyle\NodeAnalyzer\UseImportNameMatcher
*/
private $useImportNameMatcher;
/**
* @readonly
* @var \Rector\Core\NodeAnalyzer\ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(SimpleCallableNodeTraverser $simpleCallableNodeTraverser, NodeNameResolver $nodeNameResolver, ReflectionProvider $reflectionProvider, BetterNodeFinder $betterNodeFinder, UseImportNameMatcher $useImportNameMatcher, ClassAnalyzer $classAnalyzer)
public function __construct(SimpleCallableNodeTraverser $simpleCallableNodeTraverser, NodeNameResolver $nodeNameResolver, ReflectionProvider $reflectionProvider, BetterNodeFinder $betterNodeFinder, UseImportNameMatcher $useImportNameMatcher)
{
$this->simpleCallableNodeTraverser = $simpleCallableNodeTraverser;
$this->nodeNameResolver = $nodeNameResolver;
$this->reflectionProvider = $reflectionProvider;
$this->betterNodeFinder = $betterNodeFinder;
$this->useImportNameMatcher = $useImportNameMatcher;
$this->classAnalyzer = $classAnalyzer;
}
// Avoids circular reference
/**
@ -165,7 +159,7 @@ final class ShortNameResolver
*/
private function resolveFromStmtsDocBlocks(array $stmts) : array
{
$reflectionClass = $this->resolveNativeClassReflection($stmts);
$classReflection = $this->resolveClassReflection($stmts);
$shortNames = [];
$this->simpleCallableNodeTraverser->traverseNodesWithCallable($stmts, function (Node $node) use(&$shortNames) {
// speed up for nodes that are
@ -189,12 +183,12 @@ final class ShortNameResolver
});
return null;
});
return $this->fqnizeShortNames($shortNames, $reflectionClass, $stmts);
return $this->fqnizeShortNames($shortNames, $classReflection, $stmts);
}
/**
* @param Node[] $stmts
*/
private function resolveNativeClassReflection(array $stmts) : ?ReflectionClass
private function resolveClassReflection(array $stmts) : ?ClassReflection
{
$firstClassLike = $this->betterNodeFinder->findFirstInstanceOf($stmts, ClassLike::class);
if (!$firstClassLike instanceof ClassLike) {
@ -204,21 +198,21 @@ final class ShortNameResolver
if (!$this->reflectionProvider->hasClass($className)) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($className);
return $classReflection->getNativeReflection();
return $this->reflectionProvider->getClass($className);
}
/**
* @param string[] $shortNames
* @param Stmt[] $stmts
* @return array<string, string>
*/
private function fqnizeShortNames(array $shortNames, ?ReflectionClass $reflectionClass, array $stmts) : array
private function fqnizeShortNames(array $shortNames, ?ClassReflection $classReflection, array $stmts) : array
{
$shortNamesToFullyQualifiedNames = [];
$nativeReflectionClass = $classReflection instanceof ClassReflection && !$classReflection->isAnonymous() ? $classReflection->getNativeReflection() : null;
foreach ($shortNames as $shortName) {
$stmtsMatchedName = $this->useImportNameMatcher->matchNameWithStmts($shortName, $stmts);
if ($reflectionClass instanceof ReflectionClass && !$this->classAnalyzer->isAnonymousClassName($reflectionClass->getShortName())) {
$fullyQualifiedName = Reflection::expandClassName($shortName, $reflectionClass);
if ($nativeReflectionClass instanceof ReflectionClass) {
$fullyQualifiedName = Reflection::expandClassName($shortName, $nativeReflectionClass);
} elseif (\is_string($stmtsMatchedName)) {
$fullyQualifiedName = $stmtsMatchedName;
} else {

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '58d862b6f54529f25ecb994ea5e7d2c3eb69f210';
public const PACKAGE_VERSION = 'f7e1b1f57e8746e07627799b5d9813e12c1c7b56';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-03-31 03:39:54';
public const RELEASE_DATE = '2023-04-01 04:37:43';
/**
* @var int
*/

View File

@ -4,48 +4,28 @@ declare (strict_types=1);
namespace Rector\Core\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Util\StringUtils;
use Rector\NodeNameResolver\NodeNameResolver;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class ClassAnalyzer
{
/**
* @var string
* @see https://regex101.com/r/FQH6RT/2
*/
private const ANONYMOUS_CLASS_REGEX = '#^AnonymousClass\\w+$#';
/**
* @readonly
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
public function __construct(NodeNameResolver $nodeNameResolver)
{
$this->nodeNameResolver = $nodeNameResolver;
}
public function isAnonymousClassName(string $className) : bool
{
return StringUtils::isMatch($className, self::ANONYMOUS_CLASS_REGEX);
}
public function isAnonymousClass(Node $node) : bool
{
if (!$node instanceof Class_) {
return \false;
}
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if (!$parentNode instanceof New_) {
return \false;
}
if ($node->isAnonymous()) {
return \true;
}
$className = $this->nodeNameResolver->getName($node);
if ($className === null) {
return \true;
$scope = $node->getAttribute(AttributeKey::SCOPE);
if (!$scope instanceof Scope) {
return \false;
}
// match PHPStan pattern for anonymous classes
return StringUtils::isMatch($className, self::ANONYMOUS_CLASS_REGEX);
$classReflection = $scope->getClassReflection();
if ($classReflection instanceof ClassReflection) {
return $classReflection->isAnonymous();
}
return \false;
}
}

2
vendor/autoload.php vendored
View File

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

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitfbb79adddead867277f9db7383d4e715
class ComposerAutoloaderInit1d2c34c788e254b6ac517d40b0c38046
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInitfbb79adddead867277f9db7383d4e715
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitfbb79adddead867277f9db7383d4e715', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit1d2c34c788e254b6ac517d40b0c38046', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitfbb79adddead867277f9db7383d4e715', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit1d2c34c788e254b6ac517d40b0c38046', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitfbb79adddead867277f9db7383d4e715::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInitfbb79adddead867277f9db7383d4e715::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046::$files;
$requireFile = \Closure::bind(static function ($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 ComposerStaticInitfbb79adddead867277f9db7383d4e715
class ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -3130,9 +3130,9 @@ class ComposerStaticInitfbb79adddead867277f9db7383d4e715
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitfbb79adddead867277f9db7383d4e715::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitfbb79adddead867277f9db7383d4e715::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitfbb79adddead867277f9db7383d4e715::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit1d2c34c788e254b6ac517d40b0c38046::$classMap;
}, null, ClassLoader::class);
}

View File

@ -2343,17 +2343,17 @@
},
{
"name": "symfony\/console",
"version": "v6.2.7",
"version_normalized": "6.2.7.0",
"version": "v6.2.8",
"version_normalized": "6.2.8.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/symfony\/console.git",
"reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45"
"reference": "3582d68a64a86ec25240aaa521ec8bc2342b369b"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/symfony\/console\/zipball\/cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
"reference": "cbad09eb8925b6ad4fb721c7a179344dc4a19d45",
"url": "https:\/\/api.github.com\/repos\/symfony\/console\/zipball\/3582d68a64a86ec25240aaa521ec8bc2342b369b",
"reference": "3582d68a64a86ec25240aaa521ec8bc2342b369b",
"shasum": ""
},
"require": {
@ -2388,7 +2388,7 @@
"symfony\/lock": "",
"symfony\/process": ""
},
"time": "2023-02-25T17:00:03+00:00",
"time": "2023-03-29T21:42:15+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -2417,12 +2417,12 @@
"homepage": "https:\/\/symfony.com",
"keywords": [
"cli",
"command line",
"command-line",
"console",
"terminal"
],
"support": {
"source": "https:\/\/github.com\/symfony\/console\/tree\/v6.2.7"
"source": "https:\/\/github.com\/symfony\/console\/tree\/v6.2.8"
},
"funding": [
{
@ -2947,23 +2947,23 @@
},
{
"name": "symfony\/process",
"version": "v6.2.7",
"version_normalized": "6.2.7.0",
"version": "v6.2.8",
"version_normalized": "6.2.8.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/symfony\/process.git",
"reference": "680e8a2ea6b3f87aecc07a6a65a203ae573d1902"
"reference": "75ed64103df4f6615e15a7fe38b8111099f47416"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/symfony\/process\/zipball\/680e8a2ea6b3f87aecc07a6a65a203ae573d1902",
"reference": "680e8a2ea6b3f87aecc07a6a65a203ae573d1902",
"url": "https:\/\/api.github.com\/repos\/symfony\/process\/zipball\/75ed64103df4f6615e15a7fe38b8111099f47416",
"reference": "75ed64103df4f6615e15a7fe38b8111099f47416",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"time": "2023-02-24T10:42:00+00:00",
"time": "2023-03-09T16:20:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -2991,7 +2991,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https:\/\/symfony.com",
"support": {
"source": "https:\/\/github.com\/symfony\/process\/tree\/v6.2.7"
"source": "https:\/\/github.com\/symfony\/process\/tree\/v6.2.8"
},
"funding": [
{
@ -3011,17 +3011,17 @@
},
{
"name": "symfony\/string",
"version": "v6.2.7",
"version_normalized": "6.2.7.0",
"version": "v6.2.8",
"version_normalized": "6.2.8.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/symfony\/string.git",
"reference": "67b8c1eec78296b85dc1c7d9743830160218993d"
"reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/symfony\/string\/zipball\/67b8c1eec78296b85dc1c7d9743830160218993d",
"reference": "67b8c1eec78296b85dc1c7d9743830160218993d",
"url": "https:\/\/api.github.com\/repos\/symfony\/string\/zipball\/193e83bbd6617d6b2151c37fff10fa7168ebddef",
"reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef",
"shasum": ""
},
"require": {
@ -3041,7 +3041,7 @@
"symfony\/translation-contracts": "^2.0|^3.0",
"symfony\/var-exporter": "^5.4|^6.0"
},
"time": "2023-02-24T10:42:00+00:00",
"time": "2023-03-20T16:06:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3080,7 +3080,7 @@
"utf8"
],
"support": {
"source": "https:\/\/github.com\/symfony\/string\/tree\/v6.2.7"
"source": "https:\/\/github.com\/symfony\/string\/tree\/v6.2.8"
},
"funding": [
{

File diff suppressed because one or more lines are too long

View File

@ -53,9 +53,10 @@ final class DumpCompletionCommand extends Command
[$rcFile, $completionFile] = ['~/.bashrc', "/etc/bash_completion.d/{$commandName}"];
break;
}
$supportedShells = \implode(', ', $this->getSupportedShells());
$this->setHelp(<<<EOH
The <info>%command.name%</> command dumps the shell completion script required
to use shell autocompletion (currently, bash and fish completion is supported).
to use shell autocompletion (currently, {$supportedShells} completion are supported).
<comment>Static installation
-------------------</>

View File

@ -89,7 +89,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
}
public function apply(string $text) : string
{
$this->handlesHrefGracefully = $this->handlesHrefGracefully ?? 'JetBrains-JediTerm' !== \getenv('TERMINAL_EMULATOR') && (!\getenv('KONSOLE_VERSION') || (int) \getenv('KONSOLE_VERSION') > 201100);
$this->handlesHrefGracefully = $this->handlesHrefGracefully ?? 'JetBrains-JediTerm' !== \getenv('TERMINAL_EMULATOR') && (!\getenv('KONSOLE_VERSION') || (int) \getenv('KONSOLE_VERSION') > 201100) && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
if (null !== $this->href && $this->handlesHrefGracefully) {
$text = "\x1b]8;;{$this->href}\x1b\\{$text}\x1b]8;;\x1b\\";
}

View File

@ -5,7 +5,7 @@
"keywords": [
"console",
"cli",
"command line",
"command-line",
"terminal"
],
"homepage": "https:\/\/symfony.com",

View File

@ -43,12 +43,16 @@ final class EnglishInflector implements InflectorInterface
['nexo', 4, \false, \false, 'ox'],
// indices (index), appendices (appendix), prices (price)
['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
// codes (code)
['sedoc', 5, \false, \true, 'code'],
// selfies (selfie)
['seifles', 7, \true, \true, 'selfie'],
// zombies (zombie)
['seibmoz', 7, \true, \true, 'zombie'],
// movies (movie)
['seivom', 6, \true, \true, 'movie'],
// names (name)
['seman', 5, \true, \false, 'name'],
// conspectuses (conspectus), prospectuses (prospectus)
['sesutcep', 8, \true, \true, 'pectus'],
// feet (foot)