added some tests

This commit is contained in:
Fabien Potencier 2015-09-28 13:00:47 +02:00
parent d3271e1fae
commit 95c9f500e9
5 changed files with 92 additions and 46 deletions

View File

@ -21,69 +21,66 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*/ */
class UnusedTagsPass implements CompilerPassInterface class UnusedTagsPass implements CompilerPassInterface
{ {
/** private $whitelist = array(
* whitelisted tags 'console.command',
* 'config_cache.resource_checker',
* @var array 'data_collector',
*/ 'form.type',
protected $whitelist = array( 'form.type_extension',
"console.command", 'form.type_guesser',
"config_cache.resource_checker", 'kernel.cache_clearer',
"data_collector", 'kernel.cache_warmer',
"form.type", 'kernel.event_listener',
"form.type_extension", 'kernel.event_subscriber',
"form.type_guesser", 'kernel.fragment_renderer',
"kernel.cache_clearer", 'monolog.logger',
"kernel.cache_warmer", 'routing.expression_language_provider',
"kernel.event_listener", 'routing.loader',
"kernel.event_subscriber", 'security.expression_language_provider',
"kernel.fragment_renderer", 'security.remember_me_aware',
"monolog.logger", 'security.voter',
"routing.expression_language_provider", 'serializer.encoder',
"routing.loader", 'serializer.normalizer',
"security.expression_language_provider", 'templating.helper',
"security.remember_me_aware", 'translation.dumper',
"security.voter", 'translation.extractor',
"serializer.encoder", 'translation.loader',
"serializer.normalizer", 'twig.extension',
"templating.helper", 'twig.loader',
"translation.dumper", 'validator.constraint_validator',
"translation.extractor", 'validator.initializer',
"translation.loader",
"twig.extension",
"twig.loader",
"validator.constraint_validator",
"validator.initializer",
); );
public function process(ContainerBuilder $container) public function process(ContainerBuilder $container)
{ {
$compiler = $container->getCompiler(); $compiler = $container->getCompiler();
$formatter = $compiler->getLoggingFormatter(); $formatter = $compiler->getLoggingFormatter();
$tags = $container->findTags(); $tags = array_unique(array_merge($container->findTags(), $this->whitelist));
$unusedTags = $container->findUnusedTags(); foreach ($container->findUnusedTags() as $tag) {
foreach ($unusedTags as $tag) {
// skip whitelisted tags // skip whitelisted tags
if (in_array($tag, $this->whitelist)) { if (in_array($tag, $this->whitelist)) {
continue; continue;
} }
// check for typos // check for typos
$candidates = array(); $candidates = array();
foreach ($tags as $definedTag) { foreach ($tags as $definedTag) {
if ($definedTag === $tag) { if ($definedTag === $tag) {
continue; continue;
} }
if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= strlen($tag) / 3) { if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= strlen($tag) / 3) {
$candidates[] = $definedTag; $candidates[] = $definedTag;
} }
} }
$services = array_keys($container->findTaggedServiceIds($tag)); $services = array_keys($container->findTaggedServiceIds($tag));
$message = sprintf('Tag "%s" was defined on the service(s) %s, but was never used.', $tag, implode(',', $services)); $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services));
if (!empty($candidates)) { if (!empty($candidates)) {
$message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates));
} }
$compiler->addLogMessage($formatter->format($this, $message)); $compiler->addLogMessage($formatter->format($this, $message));
} }
} }

View File

@ -90,9 +90,9 @@ class FrameworkBundle extends Bundle
$container->addCompilerPass(new TranslationDumperPass()); $container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SerializerPass()); $container->addCompilerPass(new SerializerPass());
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
if ($container->getParameter('kernel.debug')) { if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new ConfigCachePass()); $container->addCompilerPass(new ConfigCachePass());

View File

@ -0,0 +1,52 @@
<?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\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
class UnusedTagsPassTest extends \PHPUnit_Framework_TestCase
{
public function testProcess()
{
$pass = new UnusedTagsPass();
$formatter = $this->getMock('Symfony\Component\DependencyInjection\Compiler\LoggingFormatter');
$formatter
->expects($this->at(0))
->method('format')
->with($pass, 'Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?')
;
$compiler = $this->getMock('Symfony\Component\DependencyInjection\Compiler\Compiler');
$compiler->expects($this->once())->method('getLoggingFormatter')->will($this->returnValue($formatter));
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder',
array('findTaggedServiceIds', 'getCompiler', 'findUnusedTags', 'findTags')
);
$container->expects($this->once())->method('getCompiler')->will($this->returnValue($compiler));
$container->expects($this->once())
->method('findTags')
->will($this->returnValue(array('kenrel.event_subscriber')));
$container->expects($this->once())
->method('findUnusedTags')
->will($this->returnValue(array('kenrel.event_subscriber', 'form.type')));
$container->expects($this->once())
->method('findTaggedServiceIds')
->with('kenrel.event_subscriber')
->will($this->returnValue(array(
'foo' => array(),
'bar' => array(),
)));
$pass->process($container);
}
}

View File

@ -20,7 +20,7 @@ class LoggingFormatter
{ {
public function formatRemoveService(CompilerPassInterface $pass, $id, $reason) public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
{ {
return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason)); return $this->format($pass, sprintf('Removed service "%s"; reason: %s.', $id, $reason));
} }
public function formatInlineService(CompilerPassInterface $pass, $id, $target) public function formatInlineService(CompilerPassInterface $pass, $id, $target)

View File

@ -91,7 +91,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private $expressionLanguageProviders = array(); private $expressionLanguageProviders = array();
/** /**
* @var array with tag names used by findTaggedServiceIds * @var string[] with tag names used by findTaggedServiceIds
*/ */
private $usedTags = array(); private $usedTags = array();
@ -1096,16 +1096,13 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
} }
/** /**
* Returns all tags not queried by findTaggedServiceIds * Returns all tags not queried by findTaggedServiceIds.
* *
* @return array An array of tags * @return string[] An array of tags
*/ */
public function findUnusedTags() public function findUnusedTags()
{ {
$tags = array_values(array_diff($this->findTags(), $this->usedTags)); return array_values(array_diff($this->findTags(), $this->usedTags));
$tags = array_unique($tags);
return $tags;
} }
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)