mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-21 18:00:10 +01:00
Merge pull request #2470 from rectorphp/argument-merge
merge Rector arguments on import
This commit is contained in:
commit
3735fd15f2
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DependencyInjection\Collector;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Contract\Rector\RectorInterface;
|
||||
use Symplify\PackageBuilder\Yaml\ParametersMerger;
|
||||
|
||||
final class RectorServiceArgumentCollector
|
||||
{
|
||||
/**
|
||||
* @var ParametersMerger
|
||||
*/
|
||||
private $parametersMerger;
|
||||
|
||||
/**
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $cachedRectorServiceKeyArguments = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parametersMerger = new ParametersMerger();
|
||||
}
|
||||
|
||||
public function getClassArgumentValue(string $serviceClass): array
|
||||
{
|
||||
return $this->cachedRectorServiceKeyArguments[$serviceClass] ?? [];
|
||||
}
|
||||
|
||||
public function collectFromServiceAndRectorClass(array $service, string $className): void
|
||||
{
|
||||
if (! is_a($className, RectorInterface::class, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($service as $argumentName => $argumentValue) {
|
||||
// is that argument?
|
||||
if (! Strings::startsWith($argumentName, '$')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->addArgumentValue($className, $argumentName, $argumentValue);
|
||||
}
|
||||
}
|
||||
|
||||
private function addArgumentValue(string $serviceClassName, string $argumentName, $argumentValue): void
|
||||
{
|
||||
if (! isset($this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName])) {
|
||||
$this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName] = $argumentValue;
|
||||
} else {
|
||||
$mergedParameters = $this->parametersMerger->merge(
|
||||
$this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName],
|
||||
$argumentValue
|
||||
);
|
||||
|
||||
$this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName] = $mergedParameters;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DependencyInjection\CompilerPass;
|
||||
|
||||
use Rector\DependencyInjection\Collector\RectorServiceArgumentCollector;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
|
||||
final class MergeImportedRectorServiceArgumentsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var RectorServiceArgumentCollector
|
||||
*/
|
||||
private $rectorServiceArgumentCollector;
|
||||
|
||||
public function __construct(RectorServiceArgumentCollector $rectorServiceArgumentCollector)
|
||||
{
|
||||
$this->rectorServiceArgumentCollector = $rectorServiceArgumentCollector;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
foreach ($containerBuilder->getDefinitions() as $id => $definition) {
|
||||
$this->completeCollectedArguments($id, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
private function completeCollectedArguments(string $serviceClass, Definition $definition): void
|
||||
{
|
||||
$cachedServiceKeyArguments = $this->rectorServiceArgumentCollector->getClassArgumentValue($serviceClass);
|
||||
if ($cachedServiceKeyArguments === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent argument override
|
||||
foreach ($cachedServiceKeyArguments as $argumentName => $argumentValue) {
|
||||
$definition->setArgument($argumentName, $argumentValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Rector\DependencyInjection\Loader;
|
||||
|
||||
use Rector\Contract\Rector\RectorInterface;
|
||||
use Rector\DependencyInjection\Collector\RectorServiceArgumentCollector;
|
||||
use Symfony\Component\Config\FileLocatorInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symplify\PackageBuilder\Yaml\FileLoader\AbstractParameterMergingYamlFileLoader;
|
||||
@ -21,10 +23,19 @@ final class TolerantRectorYamlFileLoader extends AbstractParameterMergingYamlFil
|
||||
*/
|
||||
private $classExistenceValidator;
|
||||
|
||||
public function __construct(ContainerBuilder $containerBuilder, FileLocatorInterface $fileLocator)
|
||||
{
|
||||
/**
|
||||
* @var RectorServiceArgumentCollector
|
||||
*/
|
||||
private $rectorServiceArgumentCollector;
|
||||
|
||||
public function __construct(
|
||||
ContainerBuilder $containerBuilder,
|
||||
FileLocatorInterface $fileLocator,
|
||||
RectorServiceArgumentCollector $rectorServiceArgumentCollector
|
||||
) {
|
||||
$this->parameterInImportResolver = new ParameterInImportResolver();
|
||||
$this->classExistenceValidator = new ClassExistenceValidator();
|
||||
$this->rectorServiceArgumentCollector = $rectorServiceArgumentCollector;
|
||||
|
||||
parent::__construct($containerBuilder, $fileLocator);
|
||||
}
|
||||
@ -41,19 +52,35 @@ final class TolerantRectorYamlFileLoader extends AbstractParameterMergingYamlFil
|
||||
return [];
|
||||
}
|
||||
|
||||
// @todo: merge service arguments as well
|
||||
foreach ($configuration['services'] ?? [] as $service) {
|
||||
if (! isset($service['arguments'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// dump($service['arguments']);
|
||||
}
|
||||
$this->collectRectorServiceArguments($configuration);
|
||||
|
||||
$this->classExistenceValidator->ensureClassesAreValid($configuration, $file);
|
||||
|
||||
// $configuration = $this->rectorServiceParametersShifter->process($configuration, $file);
|
||||
|
||||
return $this->parameterInImportResolver->process($configuration);
|
||||
}
|
||||
|
||||
private function collectRectorServiceArguments(array $configuration): void
|
||||
{
|
||||
if (! isset($configuration['services'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// merge service arguments as well
|
||||
foreach ($configuration['services'] as $className => $service) {
|
||||
if (! is_string($className)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip non-rectors
|
||||
if (! is_a($className, RectorInterface::class, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! is_array($service)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->rectorServiceArgumentCollector->collectFromServiceAndRectorClass($service, $className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace Rector\HttpKernel;
|
||||
|
||||
use Rector\Contract\Rector\RectorInterface;
|
||||
use Rector\DependencyInjection\Collector\RectorServiceArgumentCollector;
|
||||
use Rector\DependencyInjection\CompilerPass\MergeImportedRectorServiceArgumentsCompilerPass;
|
||||
use Rector\DependencyInjection\CompilerPass\RemoveExcludedRectorsCompilerPass;
|
||||
use Rector\DependencyInjection\Loader\TolerantRectorYamlFileLoader;
|
||||
use Symfony\Component\Config\Loader\DelegatingLoader;
|
||||
@ -29,6 +31,18 @@ final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterfa
|
||||
*/
|
||||
private $configs = [];
|
||||
|
||||
/**
|
||||
* @var RectorServiceArgumentCollector
|
||||
*/
|
||||
private $rectorServiceArgumentCollector;
|
||||
|
||||
public function __construct(string $environment, bool $debug)
|
||||
{
|
||||
$this->rectorServiceArgumentCollector = new RectorServiceArgumentCollector();
|
||||
|
||||
parent::__construct($environment, $debug);
|
||||
}
|
||||
|
||||
public function getCacheDir(): string
|
||||
{
|
||||
// manually configured, so it can be replaced in phar
|
||||
@ -77,6 +91,11 @@ final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterfa
|
||||
$containerBuilder->addCompilerPass(new AutowireInterfacesCompilerPass([RectorInterface::class]));
|
||||
|
||||
$containerBuilder->addCompilerPass(new AutoBindParametersCompilerPass());
|
||||
|
||||
// add all merged arguments of Rector services
|
||||
$containerBuilder->addCompilerPass(
|
||||
new MergeImportedRectorServiceArgumentsCompilerPass($this->rectorServiceArgumentCollector)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,7 +108,7 @@ final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterfa
|
||||
|
||||
$loaderResolver = new LoaderResolver([
|
||||
new GlobFileLoader($kernelFileLocator),
|
||||
new TolerantRectorYamlFileLoader($container, $kernelFileLocator),
|
||||
new TolerantRectorYamlFileLoader($container, $kernelFileLocator, $this->rectorServiceArgumentCollector),
|
||||
]);
|
||||
|
||||
return new DelegatingLoader($loaderResolver);
|
||||
|
@ -6,9 +6,8 @@ use Rector\Tests\Issues\Issue2451\Source\AbstractBaseHandler;
|
||||
|
||||
class Issue2451 extends AbstractBaseHandler
|
||||
{
|
||||
public function handle($params)
|
||||
public function handle()
|
||||
{
|
||||
// do something
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,9 +21,8 @@ use Rector\Tests\Issues\Issue2451\Source\AbstractBaseHandler;
|
||||
|
||||
class Issue2451 extends AbstractBaseHandler
|
||||
{
|
||||
public function handle($params): \Tomaj\NetteApi\Response\ResponseInterface
|
||||
public function handle(): \Tomaj\NetteApi\Response\ResponseInterface
|
||||
{
|
||||
// do something
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@ final class Issue2451Test extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->markTestSkipped('Resolve after removing shifter');
|
||||
|
||||
$this->doTestFile(__DIR__ . '/Fixture/fixture2451.php.inc');
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user