[DependencyInjection] made some improvments to the container compiler

- added generic repeated pass
- better optimization of services
- started adding some integration tests
This commit is contained in:
Johannes Schmitt 2011-01-08 09:39:53 +01:00 committed by Fabien Potencier
parent bdada47fad
commit e85546ef7d
7 changed files with 158 additions and 5 deletions

View File

@ -21,9 +21,15 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class InlineServiceDefinitionsPass implements CompilerPassInterface
class InlineServiceDefinitionsPass implements RepeatablePassInterface
{
protected $aliasMap;
protected $repeatedPass;
public function setRepeatedPass(RepeatedPass $repeatedPass)
{
$this->repeatedPass = $repeatedPass;
}
public function process(ContainerBuilder $container)
{

View File

@ -39,8 +39,10 @@ class PassConfig
$this->removingPasses = array(
new RemovePrivateAliasesPass(),
new ReplaceAliasByActualDefinitionPass(),
new InlineServiceDefinitionsPass(),
new RemoveUnusedDefinitionsPass(),
new RepeatedPass(array(
new InlineServiceDefinitionsPass(),
new RemoveUnusedDefinitionsPass(),
)),
);
}

View File

@ -20,8 +20,15 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class RemoveUnusedDefinitionsPass implements CompilerPassInterface
class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
{
protected $repeatedPass;
public function setRepeatedPass(RepeatedPass $repeatedPass)
{
$this->repeatedPass = $repeatedPass;
}
public function process(ContainerBuilder $container)
{
$hasChanged = false;
@ -45,7 +52,7 @@ class RemoveUnusedDefinitionsPass implements CompilerPassInterface
}
if ($hasChanged) {
$this->process($container);
$this->repeatedPass->setRepeat();
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Symfony\Component\DependencyInjection\Compiler;
/**
* Interface that must be implemented by passes that are run as part of an
* RepeatedPass.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface RepeatablePassInterface extends CompilerPassInterface
{
function setRepeatedPass(RepeatedPass $repeatedPass);
}

View File

@ -0,0 +1,46 @@
<?php
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* A pass that might be run repeatedly.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class RepeatedPass implements CompilerPassInterface
{
protected $repeat;
protected $passes;
public function __construct(array $passes)
{
foreach ($passes as $pass) {
if (!$pass instanceof RepeatablePassInterface) {
throw new \InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
}
$pass->setRepeatedPass($this);
}
$this->passes = $passes;
}
public function process(ContainerBuilder $container)
{
$this->repeat = false;
foreach ($this->passes as $pass) {
$pass->process($container);
}
if ($this->repeat) {
$this->process($container);
}
}
public function setRepeat()
{
$this->repeat = true;
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace Symfony\Tests\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* This class tests the integration of the different compiler passes
*/
class IntegrationTest extends \PHPUnit_Framework_TestCase
{
/**
* This tests that the following dependencies are correctly processed:
*
* A is public, B/C are private
* A -> C
* B -> C
*/
public function testProcessRemovesAndInlinesRecursively()
{
$container = new ContainerBuilder();
$a = $container
->register('a')
->addArgument(new Reference('c'))
;
$b = $container
->register('b')
->addArgument(new Reference('c'))
->setPublic(false)
;
$c = $container
->register('c')
->setPublic(false)
;
$container->freeze();
$this->assertTrue($container->hasDefinition('a'));
$arguments = $a->getArguments();
$this->assertSame($c, $arguments[0]);
$this->assertFalse($container->hasDefinition('b'));
$this->assertFalse($container->hasDefinition('c'));
}
public function testProcessInlinesReferencesToAliases()
{
$container = new ContainerBuilder();
$a = $container
->register('a')
->addArgument(new Reference('b'))
;
$container->setAlias('b', new Alias('c', false));
$c = $container
->register('c')
->setPublic(false)
;
$container->freeze();
$this->assertTrue($container->hasDefinition('a'));
$arguments = $a->getArguments();
$this->assertSame($c, $arguments[0]);
$this->assertFalse($container->hasAlias('b'));
$this->assertFalse($container->hasDefinition('c'));
}
}

View File

@ -2,6 +2,8 @@
namespace Symfony\Tests\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
@ -72,6 +74,7 @@ class RemoveUnusedDefinitionsPassTest extends \PHPUnit_Framework_TestCase
protected function process(ContainerBuilder $container)
{
$pass = new RemoveUnusedDefinitionsPass();
$repeatedPass = new RepeatedPass(array($pass));
$pass->process($container);
}
}