diff --git a/packages/BetterPhpDocParser/PhpDocNodeMapper.php b/packages/BetterPhpDocParser/PhpDocNodeMapper.php index 7e44f3ba687..eaa6d1f2867 100644 --- a/packages/BetterPhpDocParser/PhpDocNodeMapper.php +++ b/packages/BetterPhpDocParser/PhpDocNodeMapper.php @@ -10,6 +10,7 @@ use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeTraverser; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\CloningPhpDocNodeVisitor; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\ParentConnectingPhpDocNodeVisitor; +use RectorPrefix202308\Webmozart\Assert\Assert; /** * @see \Rector\Tests\BetterPhpDocParser\PhpDocNodeMapperTest */ @@ -44,6 +45,7 @@ final class PhpDocNodeMapper $this->parentConnectingPhpDocNodeVisitor = $parentConnectingPhpDocNodeVisitor; $this->cloningPhpDocNodeVisitor = $cloningPhpDocNodeVisitor; $this->phpDocNodeVisitors = $phpDocNodeVisitors; + Assert::notEmpty($phpDocNodeVisitors); } public function transform(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator) : void { diff --git a/packages/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.php b/packages/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.php index 60c433d999e..14bf5c7a03f 100644 --- a/packages/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.php @@ -11,6 +11,7 @@ use PHPStan\Type\Type; use Rector\Core\Exception\NotImplementedYetException; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; +use RectorPrefix202308\Webmozart\Assert\Assert; final class PHPStanStaticTypeMapper { /** @@ -24,6 +25,7 @@ final class PHPStanStaticTypeMapper public function __construct(iterable $typeMappers) { $this->typeMappers = $typeMappers; + Assert::notEmpty($typeMappers); } public function mapToPHPStanPhpDocTypeNode(Type $type) : TypeNode { diff --git a/packages/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.php b/packages/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.php index c5f335d4086..013f8e9ea88 100644 --- a/packages/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.php +++ b/packages/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDoc\TypeNodeResolver; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\Type; use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface; +use RectorPrefix202308\Webmozart\Assert\Assert; /** * @see \Rector\Tests\StaticTypeMapper\PhpDoc\PhpDocTypeMapperTest */ @@ -31,6 +32,7 @@ final class PhpDocTypeMapper { $this->phpDocTypeMappers = $phpDocTypeMappers; $this->typeNodeResolver = $typeNodeResolver; + Assert::notEmpty($phpDocTypeMappers); } public function mapToPHPStanType(TypeNode $typeNode, Node $node, NameScope $nameScope) : Type { diff --git a/packages/Testing/PHPUnit/AbstractLazyTestCase.php b/packages/Testing/PHPUnit/AbstractLazyTestCase.php index e07bd3ceeb5..45d21bc5c78 100644 --- a/packages/Testing/PHPUnit/AbstractLazyTestCase.php +++ b/packages/Testing/PHPUnit/AbstractLazyTestCase.php @@ -5,13 +5,32 @@ namespace Rector\Testing\PHPUnit; use RectorPrefix202308\Illuminate\Container\Container; use PHPUnit\Framework\TestCase; +use Rector\Core\Contract\Rector\ConfigurableRectorInterface; +use Rector\Core\Contract\Rector\PhpRectorInterface; +use Rector\Core\Contract\Rector\RectorInterface; use Rector\Core\DependencyInjection\LazyContainerFactory; +use Rector\Core\Rector\AbstractRector; +use Rector\Core\Util\Reflection\PrivatesAccessor; +use RectorPrefix202308\Webmozart\Assert\Assert; abstract class AbstractLazyTestCase extends TestCase { /** * @var \Illuminate\Container\Container|null */ private static $container; + /** + * @api + * @param string[] $configFiles + */ + protected function bootFromConfigFiles(array $configFiles) : void + { + $container = self::getContainer(); + foreach ($configFiles as $configFile) { + $configClosure = (require $configFile); + Assert::isCallable($configClosure); + $configClosure($container); + } + } /** * @template TType as object * @param class-string<TType> $class @@ -29,4 +48,35 @@ abstract class AbstractLazyTestCase extends TestCase } return self::$container; } + /** + * @api soon be used + */ + protected function forgetRectorsRules() : void + { + $container = self::getContainer(); + // remove all tagged rules + $privatesAccessor = new PrivatesAccessor(); + $privatesAccessor->propertyClosure($container, 'tags', static function (array $tags) : array { + unset($tags[RectorInterface::class]); + unset($tags[PhpRectorInterface::class]); + unset($tags[ConfigurableRectorInterface::class]); + return $tags; + }); + $rectors = $container->tagged(RectorInterface::class); + foreach ($rectors as $rector) { + $container->offsetUnset(\get_class($rector)); + } + // remove after binding too, to avoid setting configuration over and over again + $privatesAccessor->propertyClosure($container, 'afterResolvingCallbacks', static function (array $afterResolvingCallbacks) : array { + foreach (\array_keys($afterResolvingCallbacks) as $key) { + if ($key === AbstractRector::class) { + continue; + } + if (\is_a($key, RectorInterface::class, \true)) { + unset($afterResolvingCallbacks[$key]); + } + } + return $afterResolvingCallbacks; + }); + } } diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 47c352218ac..93d2ca60150 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '0633dcc1de6186ff0f5186465cf47f9d97e2baf5'; + public const PACKAGE_VERSION = '662cbb9e6b9cf4842d833965dceed8eec77a0e17'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-08-08 16:16:18'; + public const RELEASE_DATE = '2023-08-08 17:28:47'; /** * @var int */ diff --git a/src/DependencyInjection/LazyContainerFactory.php b/src/DependencyInjection/LazyContainerFactory.php index f7a2c8eabf0..399d042a4e7 100644 --- a/src/DependencyInjection/LazyContainerFactory.php +++ b/src/DependencyInjection/LazyContainerFactory.php @@ -18,6 +18,11 @@ use Rector\BetterPhpDocParser\Contract\BasePhpDocNodeVisitorInterface; use Rector\BetterPhpDocParser\Contract\PhpDocParser\PhpDocNodeDecoratorInterface; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocNodeMapper; +use Rector\BetterPhpDocParser\PhpDocNodeVisitor\ArrayTypePhpDocNodeVisitor; +use Rector\BetterPhpDocParser\PhpDocNodeVisitor\CallableTypePhpDocNodeVisitor; +use Rector\BetterPhpDocParser\PhpDocNodeVisitor\IntersectionTypeNodePhpDocNodeVisitor; +use Rector\BetterPhpDocParser\PhpDocNodeVisitor\TemplatePhpDocNodeVisitor; +use Rector\BetterPhpDocParser\PhpDocNodeVisitor\UnionTypeNodePhpDocNodeVisitor; use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser; use Rector\BetterPhpDocParser\PhpDocParser\ConstExprClassNameDecorator; use Rector\BetterPhpDocParser\PhpDocParser\DoctrineAnnotationDecorator; @@ -41,6 +46,11 @@ use Rector\Core\Application\ChangedNodeScopeRefresher; use Rector\Core\Application\FileProcessor\PhpFileProcessor; use Rector\Core\Configuration\ConfigInitializer; use Rector\Core\Configuration\CurrentNodeProvider; +use Rector\Core\Console\Command\ListRulesCommand; +use Rector\Core\Console\Command\ProcessCommand; +use Rector\Core\Console\Command\SetupCICommand; +use Rector\Core\Console\Command\WorkerCommand; +use Rector\Core\Console\ConsoleApplication; use Rector\Core\Console\Output\OutputFormatterCollector; use Rector\Core\Console\Style\RectorStyle; use Rector\Core\Console\Style\SymfonyStyleFactory; @@ -169,7 +179,10 @@ use Rector\StaticTypeMapper\PhpParser\NullableTypeNodeMapper; use Rector\StaticTypeMapper\PhpParser\StringNodeMapper; use Rector\StaticTypeMapper\PhpParser\UnionTypeNodeMapper; use Rector\StaticTypeMapper\StaticTypeMapper; +use Rector\Utils\Command\MissingInSetCommand; +use Rector\Utils\Command\OutsideAnySetCommand; use RectorPrefix202308\Symfony\Component\Console\Application; +use RectorPrefix202308\Symfony\Component\Console\Command\Command; use RectorPrefix202308\Symfony\Component\Console\Style\SymfonyStyle; use RectorPrefix202308\Webmozart\Assert\Assert; final class LazyContainerFactory @@ -178,6 +191,10 @@ final class LazyContainerFactory * @var array<class-string<NodeNameResolverInterface>> */ private const NODE_NAME_RESOLVER_CLASSES = [ClassConstFetchNameResolver::class, ClassConstNameResolver::class, ClassNameResolver::class, EmptyNameResolver::class, FuncCallNameResolver::class, FunctionNameResolver::class, NameNameResolver::class, ParamNameResolver::class, PropertyNameResolver::class, UseNameResolver::class, VariableNameResolver::class]; + /** + * @var array<class-string<BasePhpDocNodeVisitorInterface>> + */ + private const BASE_PHP_DOC_NODE_VISITORS = [ArrayTypePhpDocNodeVisitor::class, CallableTypePhpDocNodeVisitor::class, IntersectionTypeNodePhpDocNodeVisitor::class, TemplatePhpDocNodeVisitor::class, UnionTypeNodePhpDocNodeVisitor::class]; /** * @var array<class-string<AnnotationToAttributeMapperInterface>> */ @@ -221,12 +238,12 @@ final class LazyContainerFactory /** * @api used as next container factory */ - public function create() : Container + public function create() : LazyRectorConfig { $lazyRectorConfig = new LazyRectorConfig(); // setup base parameters - from RectorConfig // make use of https://github.com/symplify/easy-parallel - // $rectorConfig->import(EasyParallelConfig::FILE_PATH); + // $lazyRectorConfig->import(EasyParallelConfig::FILE_PATH); $lazyRectorConfig->paths([]); $lazyRectorConfig->skip([]); $lazyRectorConfig->autoloadPaths([]); @@ -240,6 +257,8 @@ final class LazyContainerFactory $lazyRectorConfig->fileExtensions(['php']); $lazyRectorConfig->cacheDirectory(\sys_get_temp_dir() . '/rector_cached_files'); $lazyRectorConfig->containerCacheDirectory(\sys_get_temp_dir()); + // make use of https://github.com/symplify/easy-parallel + // $lazyRectorConfig->import(EasyParallelConfig::FILE_PATH); $lazyRectorConfig->singleton(Application::class, static function () : Application { $application = new Application(); // @todo inject commands @@ -255,10 +274,18 @@ final class LazyContainerFactory $inflectorFactory = new InflectorFactory(); return $inflectorFactory->build(); }); - $lazyRectorConfig->singleton(PhpFileProcessor::class); + $lazyRectorConfig->singleton(ConsoleApplication::class, ConsoleApplication::class); + $lazyRectorConfig->when(ConsoleApplication::class)->needs('$commands')->giveTagged(Command::class); $lazyRectorConfig->tag(PhpFileProcessor::class, FileProcessorInterface::class); - $lazyRectorConfig->singleton(NonPhpFileProcessor::class); $lazyRectorConfig->tag(NonPhpFileProcessor::class, FileProcessorInterface::class); + $lazyRectorConfig->tag(ProcessCommand::class, Command::class); + $lazyRectorConfig->tag(WorkerCommand::class, Command::class); + $lazyRectorConfig->tag(SetupCICommand::class, Command::class); + $lazyRectorConfig->tag(ListRulesCommand::class, Command::class); + $lazyRectorConfig->when(ListRulesCommand::class)->needs('$rectors')->giveTagged(RectorInterface::class); + // dev + $lazyRectorConfig->tag(MissingInSetCommand::class, Command::class); + $lazyRectorConfig->tag(OutsideAnySetCommand::class, Command::class); $lazyRectorConfig->when(NonPhpFileProcessor::class)->needs('$nonPhpRectors')->giveTagged(NonPhpRectorInterface::class); $lazyRectorConfig->when(ApplicationFileProcessor::class)->needs('$fileProcessors')->giveTagged(FileProcessorInterface::class); $lazyRectorConfig->when(FileFactory::class)->needs('$fileProcessors')->giveTagged(FileProcessorInterface::class); @@ -277,6 +304,10 @@ final class LazyContainerFactory }); // tagged services $lazyRectorConfig->when(BetterPhpDocParser::class)->needs('$phpDocNodeDecorators')->giveTagged(PhpDocNodeDecoratorInterface::class); + $lazyRectorConfig->afterResolving(ConditionalTypeForParameterMapper::class, static function (ConditionalTypeForParameterMapper $conditionalTypeForParameterMapper, Container $container) : void { + $phpStanStaticTypeMapper = $container->make(PHPStanStaticTypeMapper::class); + $conditionalTypeForParameterMapper->autowire($phpStanStaticTypeMapper); + }); $lazyRectorConfig->when(PHPStanStaticTypeMapper::class)->needs('$typeMappers')->giveTagged(TypeMapperInterface::class); $lazyRectorConfig->when(PhpDocTypeMapper::class)->needs('$phpDocTypeMappers')->giveTagged(PhpDocTypeMapperInterface::class); $lazyRectorConfig->when(PhpParserNodeMapper::class)->needs('$phpParserNodeMappers')->giveTagged(PhpParserNodeMapperInterface::class); @@ -288,13 +319,14 @@ final class LazyContainerFactory }); $this->registerTagged($lazyRectorConfig, self::PHP_PARSER_NODE_MAPPER_CLASSES, PhpParserNodeMapperInterface::class); $this->registerTagged($lazyRectorConfig, self::PHP_DOC_NODE_DECORATOR_CLASSES, PhpDocNodeDecoratorInterface::class); + $this->registerTagged($lazyRectorConfig, self::BASE_PHP_DOC_NODE_VISITORS, BasePhpDocNodeVisitorInterface::class); $this->registerTagged($lazyRectorConfig, self::TYPE_MAPPER_CLASSES, TypeMapperInterface::class); $this->registerTagged($lazyRectorConfig, self::PHPDOC_TYPE_MAPPER_CLASSES, PhpDocTypeMapperInterface::class); $this->registerTagged($lazyRectorConfig, self::NODE_NAME_RESOLVER_CLASSES, NodeNameResolverInterface::class); $this->registerTagged($lazyRectorConfig, self::NODE_TYPE_RESOLVER_CLASSES, NodeTypeResolverInterface::class); $this->registerTagged($lazyRectorConfig, self::OUTPUT_FORMATTER_CLASSES, OutputFormatterInterface::class); $this->registerTagged($lazyRectorConfig, self::CLASS_NAME_IMPORT_SKIPPER_CLASSES, ClassNameImportSkipVoterInterface::class); - $lazyRectorConfig->alias(RectorStyle::class, SymfonyStyle::class); + $lazyRectorConfig->alias(SymfonyStyle::class, RectorStyle::class); $lazyRectorConfig->singleton(SymfonyStyle::class, static function (Container $container) : SymfonyStyle { $symfonyStyleFactory = $container->make(SymfonyStyleFactory::class); return $symfonyStyleFactory->create(); @@ -320,10 +352,22 @@ final class LazyContainerFactory $lazyRectorConfig->afterResolving(PlainValueParser::class, static function (PlainValueParser $plainValueParser, Container $container) : void { $plainValueParser->autowire($container->make(StaticDoctrineAnnotationParser::class), $container->make(ArrayParser::class)); }); + $lazyRectorConfig->afterResolving(\Rector\PHPStanStaticTypeMapper\TypeMapper\UnionTypeMapper::class, static function (\Rector\PHPStanStaticTypeMapper\TypeMapper\UnionTypeMapper $unionTypeMapper, Container $container) : void { + $phpStanStaticTypeMapper = $container->make(PHPStanStaticTypeMapper::class); + $unionTypeMapper->autowire($phpStanStaticTypeMapper); + }); $lazyRectorConfig->singleton(Parser::class, static function (Container $container) { $phpstanServiceFactory = $container->make(PHPStanServicesFactory::class); return $phpstanServiceFactory->createPHPStanParser(); }); + $lazyRectorConfig->afterResolving(CurlyListNodeAnnotationToAttributeMapper::class, static function (CurlyListNodeAnnotationToAttributeMapper $curlyListNodeAnnotationToAttributeMapper, Container $container) : void { + $annotationToAttributeMapper = $container->make(AnnotationToAttributeMapper::class); + $curlyListNodeAnnotationToAttributeMapper->autowire($annotationToAttributeMapper); + }); + $lazyRectorConfig->afterResolving(DoctrineAnnotationAnnotationToAttributeMapper::class, static function (DoctrineAnnotationAnnotationToAttributeMapper $doctrineAnnotationAnnotationToAttributeMapper, Container $container) : void { + $annotationToAttributeMapper = $container->make(AnnotationToAttributeMapper::class); + $doctrineAnnotationAnnotationToAttributeMapper->autowire($annotationToAttributeMapper); + }); $lazyRectorConfig->when(PHPStanNodeScopeResolver::class)->needs('$nodeVisitors')->giveTagged(ScopeResolverNodeVisitorInterface::class); $this->registerTagged($lazyRectorConfig, self::SCOPE_RESOLVER_NODE_VISITOR_CLASSES, ScopeResolverNodeVisitorInterface::class); // phpstan factory diff --git a/vendor/autoload.php b/vendor/autoload.php index a07380ff8fe..900a5221f40 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) { require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit1b113c9815d4988cb1b1dea761a5a8f0::getLoader(); +return ComposerAutoloaderInit8ed71ddb3e0f1755614c4e4416fa8e8e::getLoader(); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 5e3e1da7650..c29eddaf27c 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit1b113c9815d4988cb1b1dea761a5a8f0 +class ComposerAutoloaderInit8ed71ddb3e0f1755614c4e4416fa8e8e { private static $loader; @@ -22,17 +22,17 @@ class ComposerAutoloaderInit1b113c9815d4988cb1b1dea761a5a8f0 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit1b113c9815d4988cb1b1dea761a5a8f0', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit8ed71ddb3e0f1755614c4e4416fa8e8e', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit1b113c9815d4988cb1b1dea761a5a8f0', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit8ed71ddb3e0f1755614c4e4416fa8e8e', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index d7147179b6d..84e7dc632a7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0 +class ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', @@ -3004,9 +3004,9 @@ class ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0 public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit1b113c9815d4988cb1b1dea761a5a8f0::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit8ed71ddb3e0f1755614c4e4416fa8e8e::$classMap; }, null, ClassLoader::class); }