From a0f581ba9dba877df1ba8a24adc4db9fbb57d7c1 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 11 Dec 2019 14:12:38 +0100 Subject: [PATCH] [FrameworkBundle][DependencyInjection] Skip removed ids in the lint container command and its associated pass --- .../Command/ContainerLintCommand.php | 45 ++++++++++++++++--- .../Compiler/CheckTypeDeclarationsPass.php | 13 ++++-- .../CheckTypeDeclarationsPassTest.php | 12 +++++ 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php index 10b3cf1b0d..1f4ffe59af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php @@ -14,13 +14,17 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\FileLocator; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\HttpKernel\Kernel; final class ContainerLintCommand extends Command { @@ -47,13 +51,18 @@ final class ContainerLintCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output): int { - $container = $this->getContainerBuilder(); + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + try { + $container = $this->getContainerBuilder(); + } catch (RuntimeException $e) { + $errorIo->error($e->getMessage()); + + return 2; + } - $container->setParameter('container.build_hash', 'lint_container'); $container->setParameter('container.build_time', time()); - $container->setParameter('container.build_id', 'lint_container'); - - $container->addCompilerPass(new CheckTypeDeclarationsPass(true), PassConfig::TYPE_AFTER_REMOVING, -100); $container->compile(); @@ -67,22 +76,44 @@ final class ContainerLintCommand extends Command } $kernel = $this->getApplication()->getKernel(); + $kernelContainer = $kernel->getContainer(); + + if (!$kernel->isDebug() || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { + if (!$kernel instanceof Kernel) { + throw new RuntimeException("This command does not support the console application's kernel."); + } - if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { $buildContainer = \Closure::bind(function (): ContainerBuilder { $this->initializeBundles(); return $this->buildContainer(); }, $kernel, \get_class($kernel)); $container = $buildContainer(); + + $skippedIds = []; } else { - (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); + if (!$kernelContainer instanceof Container) { + throw new RuntimeException("This command does not support the console application kernel's container."); + } + + (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); $refl = new \ReflectionProperty($parameterBag, 'resolved'); $refl->setAccessible(true); $refl->setValue($parameterBag, true); + + $passConfig = $container->getCompilerPassConfig(); + $passConfig->setRemovingPasses([]); + $passConfig->setAfterRemovingPasses([]); + + $skippedIds = $kernelContainer->getRemovedIds(); } + $container->setParameter('container.build_hash', 'lint_container'); + $container->setParameter('container.build_id', 'lint_container'); + + $container->addCompilerPass(new CheckTypeDeclarationsPass(true, $skippedIds), PassConfig::TYPE_AFTER_REMOVING, -100); + return $this->containerBuilder = $container; } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index 5a3dc72b43..0743cbbb5f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -42,16 +42,19 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass private const SCALAR_TYPES = ['int', 'float', 'bool', 'string']; private $autoload; + private $skippedIds; private $expressionLanguage; /** - * @param bool $autoload Whether services who's class in not loaded should be checked or not. - * Defaults to false to save loading code during compilation. + * @param bool $autoload Whether services who's class in not loaded should be checked or not. + * Defaults to false to save loading code during compilation. + * @param array $skippedIds An array indexed by the service ids to skip */ - public function __construct(bool $autoload = false) + public function __construct(bool $autoload = false, array $skippedIds = []) { $this->autoload = $autoload; + $this->skippedIds = $skippedIds; } /** @@ -59,6 +62,10 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass */ protected function processValue($value, $isRoot = false) { + if (isset($this->skippedIds[$this->currentId])) { + return $value; + } + if (!$value instanceof Definition || $value->hasErrors()) { return parent::processValue($value, $isRoot); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index 4729c43b93..13c34e156c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -669,4 +669,16 @@ class CheckTypeDeclarationsPassTest extends TestCase $this->addToAssertionCount(1); } + + public function testProcessSkipSkippedIds() + { + $container = new ContainerBuilder(); + $container + ->register('foobar', BarMethodCall::class) + ->addMethodCall('setArray', ['a string']); + + (new CheckTypeDeclarationsPass(true, ['foobar' => true]))->process($container); + + $this->addToAssertionCount(1); + } }