[DependencyInjection] Sort the CompilerPass by priority
This commit is contained in:
parent
fce02990f2
commit
d17c1a9734
@ -1,6 +1,11 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
3.2.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()`
|
||||||
|
|
||||||
3.0.0
|
3.0.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -65,12 +65,20 @@ class Compiler
|
|||||||
/**
|
/**
|
||||||
* Adds a pass to the PassConfig.
|
* Adds a pass to the PassConfig.
|
||||||
*
|
*
|
||||||
* @param CompilerPassInterface $pass A compiler pass
|
* @param CompilerPassInterface $pass A compiler pass
|
||||||
* @param string $type The type of the pass
|
* @param string $type The type of the pass
|
||||||
|
* @param int $priority Used to sort the passes
|
||||||
*/
|
*/
|
||||||
public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
|
public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/**, $priority = 0*/)
|
||||||
{
|
{
|
||||||
$this->passConfig->addPass($pass, $type);
|
// For BC
|
||||||
|
if (func_num_args() >= 3) {
|
||||||
|
$priority = func_get_arg(2);
|
||||||
|
} else {
|
||||||
|
$priority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->passConfig->addPass($pass, $type, $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ class PassConfig
|
|||||||
{
|
{
|
||||||
$this->mergePass = new MergeExtensionConfigurationPass();
|
$this->mergePass = new MergeExtensionConfigurationPass();
|
||||||
|
|
||||||
$this->optimizationPasses = array(
|
$this->optimizationPasses = array(array(
|
||||||
new ExtensionCompilerPass(),
|
new ExtensionCompilerPass(),
|
||||||
new ResolveDefinitionTemplatesPass(),
|
new ResolveDefinitionTemplatesPass(),
|
||||||
new DecoratorServicePass(),
|
new DecoratorServicePass(),
|
||||||
@ -51,9 +51,9 @@ class PassConfig
|
|||||||
new AnalyzeServiceReferencesPass(true),
|
new AnalyzeServiceReferencesPass(true),
|
||||||
new CheckCircularReferencesPass(),
|
new CheckCircularReferencesPass(),
|
||||||
new CheckReferenceValidityPass(),
|
new CheckReferenceValidityPass(),
|
||||||
);
|
));
|
||||||
|
|
||||||
$this->removingPasses = array(
|
$this->removingPasses = array(array(
|
||||||
new RemovePrivateAliasesPass(),
|
new RemovePrivateAliasesPass(),
|
||||||
new ReplaceAliasByActualDefinitionPass(),
|
new ReplaceAliasByActualDefinitionPass(),
|
||||||
new RemoveAbstractDefinitionsPass(),
|
new RemoveAbstractDefinitionsPass(),
|
||||||
@ -64,98 +64,111 @@ class PassConfig
|
|||||||
new RemoveUnusedDefinitionsPass(),
|
new RemoveUnusedDefinitionsPass(),
|
||||||
)),
|
)),
|
||||||
new CheckExceptionOnInvalidReferenceBehaviorPass(),
|
new CheckExceptionOnInvalidReferenceBehaviorPass(),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all passes in order to be processed.
|
* Returns all passes in order to be processed.
|
||||||
*
|
*
|
||||||
* @return array An array of all passes to process
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getPasses()
|
public function getPasses()
|
||||||
{
|
{
|
||||||
return array_merge(
|
return array_merge(
|
||||||
array($this->mergePass),
|
array($this->mergePass),
|
||||||
$this->beforeOptimizationPasses,
|
$this->getBeforeOptimizationPasses(),
|
||||||
$this->optimizationPasses,
|
$this->getOptimizationPasses(),
|
||||||
$this->beforeRemovingPasses,
|
$this->getBeforeRemovingPasses(),
|
||||||
$this->removingPasses,
|
$this->getRemovingPasses(),
|
||||||
$this->afterRemovingPasses
|
$this->getAfterRemovingPasses()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a pass.
|
* Adds a pass.
|
||||||
*
|
*
|
||||||
* @param CompilerPassInterface $pass A Compiler pass
|
* @param CompilerPassInterface $pass A Compiler pass
|
||||||
* @param string $type The pass type
|
* @param string $type The pass type
|
||||||
|
* @param int $priority Used to sort the passes
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException when a pass type doesn't exist
|
* @throws InvalidArgumentException when a pass type doesn't exist
|
||||||
*/
|
*/
|
||||||
public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION)
|
public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION/*, $priority = 0*/)
|
||||||
{
|
{
|
||||||
|
// For BC
|
||||||
|
if (func_num_args() >= 3) {
|
||||||
|
$priority = func_get_arg(2);
|
||||||
|
} else {
|
||||||
|
$priority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
$property = $type.'Passes';
|
$property = $type.'Passes';
|
||||||
if (!isset($this->$property)) {
|
if (!isset($this->$property)) {
|
||||||
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
|
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->{$property}[] = $pass;
|
$passes = &$this->$property;
|
||||||
|
|
||||||
|
if (!isset($passes[$priority])) {
|
||||||
|
$passes[$priority] = array();
|
||||||
|
}
|
||||||
|
$passes[$priority][] = $pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the AfterRemoving pass.
|
* Gets all passes for the AfterRemoving pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getAfterRemovingPasses()
|
public function getAfterRemovingPasses()
|
||||||
{
|
{
|
||||||
return $this->afterRemovingPasses;
|
return $this->sortPasses($this->afterRemovingPasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the BeforeOptimization pass.
|
* Gets all passes for the BeforeOptimization pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getBeforeOptimizationPasses()
|
public function getBeforeOptimizationPasses()
|
||||||
{
|
{
|
||||||
return $this->beforeOptimizationPasses;
|
return $this->sortPasses($this->beforeOptimizationPasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the BeforeRemoving pass.
|
* Gets all passes for the BeforeRemoving pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getBeforeRemovingPasses()
|
public function getBeforeRemovingPasses()
|
||||||
{
|
{
|
||||||
return $this->beforeRemovingPasses;
|
return $this->sortPasses($this->beforeRemovingPasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the Optimization pass.
|
* Gets all passes for the Optimization pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getOptimizationPasses()
|
public function getOptimizationPasses()
|
||||||
{
|
{
|
||||||
return $this->optimizationPasses;
|
return $this->sortPasses($this->optimizationPasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the Removing pass.
|
* Gets all passes for the Removing pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface[]
|
||||||
*/
|
*/
|
||||||
public function getRemovingPasses()
|
public function getRemovingPasses()
|
||||||
{
|
{
|
||||||
return $this->removingPasses;
|
return $this->sortPasses($this->removingPasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all passes for the Merge pass.
|
* Gets all passes for the Merge pass.
|
||||||
*
|
*
|
||||||
* @return array An array of passes
|
* @return CompilerPassInterface
|
||||||
*/
|
*/
|
||||||
public function getMergePass()
|
public function getMergePass()
|
||||||
{
|
{
|
||||||
@ -175,50 +188,69 @@ class PassConfig
|
|||||||
/**
|
/**
|
||||||
* Sets the AfterRemoving passes.
|
* Sets the AfterRemoving passes.
|
||||||
*
|
*
|
||||||
* @param array $passes An array of passes
|
* @param CompilerPassInterface[] $passes
|
||||||
*/
|
*/
|
||||||
public function setAfterRemovingPasses(array $passes)
|
public function setAfterRemovingPasses(array $passes)
|
||||||
{
|
{
|
||||||
$this->afterRemovingPasses = $passes;
|
$this->afterRemovingPasses = array($passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the BeforeOptimization passes.
|
* Sets the BeforeOptimization passes.
|
||||||
*
|
*
|
||||||
* @param array $passes An array of passes
|
* @param CompilerPassInterface[] $passes
|
||||||
*/
|
*/
|
||||||
public function setBeforeOptimizationPasses(array $passes)
|
public function setBeforeOptimizationPasses(array $passes)
|
||||||
{
|
{
|
||||||
$this->beforeOptimizationPasses = $passes;
|
$this->beforeOptimizationPasses = array($passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the BeforeRemoving passes.
|
* Sets the BeforeRemoving passes.
|
||||||
*
|
*
|
||||||
* @param array $passes An array of passes
|
* @param CompilerPassInterface[] $passes
|
||||||
*/
|
*/
|
||||||
public function setBeforeRemovingPasses(array $passes)
|
public function setBeforeRemovingPasses(array $passes)
|
||||||
{
|
{
|
||||||
$this->beforeRemovingPasses = $passes;
|
$this->beforeRemovingPasses = array($passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Optimization passes.
|
* Sets the Optimization passes.
|
||||||
*
|
*
|
||||||
* @param array $passes An array of passes
|
* @param CompilerPassInterface[] $passes
|
||||||
*/
|
*/
|
||||||
public function setOptimizationPasses(array $passes)
|
public function setOptimizationPasses(array $passes)
|
||||||
{
|
{
|
||||||
$this->optimizationPasses = $passes;
|
$this->optimizationPasses = array($passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Removing passes.
|
* Sets the Removing passes.
|
||||||
*
|
*
|
||||||
* @param array $passes An array of passes
|
* @param CompilerPassInterface[] $passes
|
||||||
*/
|
*/
|
||||||
public function setRemovingPasses(array $passes)
|
public function setRemovingPasses(array $passes)
|
||||||
{
|
{
|
||||||
$this->removingPasses = $passes;
|
$this->removingPasses = array($passes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort passes by priority.
|
||||||
|
*
|
||||||
|
* @param array $passes CompilerPassInterface instances with their priority as key.
|
||||||
|
*
|
||||||
|
* @return CompilerPassInterface[]
|
||||||
|
*/
|
||||||
|
private function sortPasses(array $passes)
|
||||||
|
{
|
||||||
|
if (0 === count($passes)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
krsort($passes);
|
||||||
|
|
||||||
|
// Flatten the array
|
||||||
|
return call_user_func_array('array_merge', $passes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,14 +298,22 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
|||||||
/**
|
/**
|
||||||
* Adds a compiler pass.
|
* Adds a compiler pass.
|
||||||
*
|
*
|
||||||
* @param CompilerPassInterface $pass A compiler pass
|
* @param CompilerPassInterface $pass A compiler pass
|
||||||
* @param string $type The type of compiler pass
|
* @param string $type The type of compiler pass
|
||||||
|
* @param int $priority Used to sort the passes
|
||||||
*
|
*
|
||||||
* @return ContainerBuilder The current instance
|
* @return ContainerBuilder The current instance
|
||||||
*/
|
*/
|
||||||
public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
|
public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/**, $priority = 0*/)
|
||||||
{
|
{
|
||||||
$this->getCompiler()->addPass($pass, $type);
|
// For BC
|
||||||
|
if (func_num_args() >= 3) {
|
||||||
|
$priority = func_get_arg(2);
|
||||||
|
} else {
|
||||||
|
$priority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getCompiler()->addPass($pass, $type, $priority);
|
||||||
|
|
||||||
$this->addObjectResource($pass);
|
$this->addObjectResource($pass);
|
||||||
|
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Guilhem N <egetick@gmail.com>
|
||||||
|
*/
|
||||||
|
class PassConfigTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testPassOrdering()
|
||||||
|
{
|
||||||
|
$config = new PassConfig();
|
||||||
|
|
||||||
|
$pass1 = $this->getMock(CompilerPassInterface::class);
|
||||||
|
$config->addPass($pass1, PassConfig::TYPE_BEFORE_OPTIMIZATION, 10);
|
||||||
|
|
||||||
|
$pass2 = $this->getMock(CompilerPassInterface::class);
|
||||||
|
$config->addPass($pass2, PassConfig::TYPE_BEFORE_OPTIMIZATION, 30);
|
||||||
|
|
||||||
|
$this->assertSame(array($pass2, $pass1), $config->getBeforeOptimizationPasses());
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';
|
|||||||
use Symfony\Bridge\PhpUnit\ErrorAssert;
|
use Symfony\Bridge\PhpUnit\ErrorAssert;
|
||||||
use Symfony\Component\Config\Resource\ResourceInterface;
|
use Symfony\Component\Config\Resource\ResourceInterface;
|
||||||
use Symfony\Component\DependencyInjection\Alias;
|
use Symfony\Component\DependencyInjection\Alias;
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
@ -284,10 +285,14 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$builder = new ContainerBuilder();
|
$builder = new ContainerBuilder();
|
||||||
$builder->setResourceTracking(false);
|
$builder->setResourceTracking(false);
|
||||||
$builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses();
|
$defaultPasses = $builder->getCompiler()->getPassConfig()->getPasses();
|
||||||
$builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'));
|
$builder->addCompilerPass($pass1 = $this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'), PassConfig::TYPE_BEFORE_OPTIMIZATION, -5);
|
||||||
|
$builder->addCompilerPass($pass2 = $this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'), PassConfig::TYPE_BEFORE_OPTIMIZATION, 10);
|
||||||
|
|
||||||
$this->assertCount(count($builder->getCompiler()->getPassConfig()->getPasses()) - 1, $builderCompilerPasses);
|
$passes = $builder->getCompiler()->getPassConfig()->getPasses();
|
||||||
|
$this->assertCount(count($passes) - 2, $defaultPasses);
|
||||||
|
// Pass 1 is executed later
|
||||||
|
$this->assertTrue(array_search($pass1, $passes, true) > array_search($pass2, $passes, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateService()
|
public function testCreateService()
|
||||||
|
Reference in New Issue
Block a user