Skip to content

Commit

Permalink
[DX] Laravel container + test case improvements (#4725)
Browse files Browse the repository at this point in the history
Co-authored-by: GitHub Action <actions@github.com>
  • Loading branch information
TomasVotruba and actions-user committed Aug 8, 2023
1 parent 0633dcc commit 662cbb9
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 65 deletions.
2 changes: 2 additions & 0 deletions packages/BetterPhpDocParser/PhpDocNodeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rector\PhpDocParser\PhpDocParser\PhpDocNodeTraverser;
use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\CloningPhpDocNodeVisitor;
use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\ParentConnectingPhpDocNodeVisitor;
use Webmozart\Assert\Assert;

/**
* @see \Rector\Tests\BetterPhpDocParser\PhpDocNodeMapperTest
Expand All @@ -26,6 +27,7 @@ public function __construct(
private readonly CloningPhpDocNodeVisitor $cloningPhpDocNodeVisitor,
private readonly iterable $phpDocNodeVisitors
) {
Assert::notEmpty($phpDocNodeVisitors);
}

public function transform(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator): void
Expand Down
2 changes: 2 additions & 0 deletions packages/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Rector\Core\Exception\NotImplementedYetException;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Webmozart\Assert\Assert;

final class PHPStanStaticTypeMapper
{
Expand All @@ -21,6 +22,7 @@ final class PHPStanStaticTypeMapper
public function __construct(
private readonly iterable $typeMappers
) {
Assert::notEmpty($typeMappers);
}

public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode
Expand Down
2 changes: 2 additions & 0 deletions packages/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Type;
use Rector\StaticTypeMapper\Contract\PhpDocParser\PhpDocTypeMapperInterface;
use Webmozart\Assert\Assert;

/**
* @see \Rector\Tests\StaticTypeMapper\PhpDoc\PhpDocTypeMapperTest
Expand All @@ -23,6 +24,7 @@ public function __construct(
private readonly iterable $phpDocTypeMappers,
private readonly TypeNodeResolver $typeNodeResolver
) {
Assert::notEmpty($phpDocTypeMappers);
}

public function mapToPHPStanType(TypeNode $typeNode, Node $node, NameScope $nameScope): Type
Expand Down
64 changes: 64 additions & 0 deletions packages/Testing/PHPUnit/AbstractLazyTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,34 @@

use 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 Webmozart\Assert\Assert;

abstract class AbstractLazyTestCase extends TestCase
{
private static ?Container $container = null;

/**
* @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
Expand All @@ -31,4 +53,46 @@ protected static function getContainer(): Container

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($rector::class);
}

// 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;
}
);
}
}

This file was deleted.

This file was deleted.

106 changes: 100 additions & 6 deletions src/DependencyInjection/LazyContainerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
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;
Expand All @@ -42,6 +47,11 @@
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;
Expand Down Expand Up @@ -170,7 +180,10 @@
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 Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;
use Webmozart\Assert\Assert;

Expand All @@ -193,6 +206,17 @@ final class LazyContainerFactory
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>>
*/
Expand Down Expand Up @@ -346,13 +370,13 @@ 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([]);
Expand All @@ -373,6 +397,9 @@ public function create(): Container
$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();

Expand All @@ -393,12 +420,27 @@ public function create(): Container
return $inflectorFactory->build();
});

$lazyRectorConfig->singleton(PhpFileProcessor::class);
$lazyRectorConfig->tag(PhpFileProcessor::class, FileProcessorInterface::class);
$lazyRectorConfig->singleton(ConsoleApplication::class, ConsoleApplication::class);
$lazyRectorConfig->when(ConsoleApplication::class)
->needs('$commands')
->giveTagged(Command::class);

$lazyRectorConfig->singleton(NonPhpFileProcessor::class);
$lazyRectorConfig->tag(PhpFileProcessor::class, FileProcessorInterface::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);
Expand Down Expand Up @@ -443,6 +485,17 @@ static function (Container $container): DynamicSourceLocatorProvider {
->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);
Expand Down Expand Up @@ -495,11 +548,19 @@ static function (AbstractRector $rector, Container $container): void {
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);
Expand All @@ -511,7 +572,7 @@ static function (AbstractRector $rector, Container $container): void {
ClassNameImportSkipVoterInterface::class
);

$lazyRectorConfig->alias(RectorStyle::class, SymfonyStyle::class);
$lazyRectorConfig->alias(SymfonyStyle::class, RectorStyle::class);

$lazyRectorConfig->singleton(
SymfonyStyle::class,
Expand Down Expand Up @@ -585,11 +646,44 @@ static function (PlainValueParser $plainValueParser, Container $container): void
}
);

$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);
Expand Down

0 comments on commit 662cbb9

Please sign in to comment.