diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index 61722072e4..ed852fd041 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -21,69 +21,66 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; */ class UnusedTagsPass implements CompilerPassInterface { - /** - * whitelisted tags - * - * @var array - */ - protected $whitelist = array( - "console.command", - "config_cache.resource_checker", - "data_collector", - "form.type", - "form.type_extension", - "form.type_guesser", - "kernel.cache_clearer", - "kernel.cache_warmer", - "kernel.event_listener", - "kernel.event_subscriber", - "kernel.fragment_renderer", - "monolog.logger", - "routing.expression_language_provider", - "routing.loader", - "security.expression_language_provider", - "security.remember_me_aware", - "security.voter", - "serializer.encoder", - "serializer.normalizer", - "templating.helper", - "translation.dumper", - "translation.extractor", - "translation.loader", - "twig.extension", - "twig.loader", - "validator.constraint_validator", - "validator.initializer", + private $whitelist = array( + 'console.command', + 'config_cache.resource_checker', + 'data_collector', + 'form.type', + 'form.type_extension', + 'form.type_guesser', + 'kernel.cache_clearer', + 'kernel.cache_warmer', + 'kernel.event_listener', + 'kernel.event_subscriber', + 'kernel.fragment_renderer', + 'monolog.logger', + 'routing.expression_language_provider', + 'routing.loader', + 'security.expression_language_provider', + 'security.remember_me_aware', + 'security.voter', + 'serializer.encoder', + 'serializer.normalizer', + 'templating.helper', + 'translation.dumper', + 'translation.extractor', + 'translation.loader', + 'twig.extension', + 'twig.loader', + 'validator.constraint_validator', + 'validator.initializer', ); public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); - $tags = $container->findTags(); + $tags = array_unique(array_merge($container->findTags(), $this->whitelist)); - $unusedTags = $container->findUnusedTags(); - foreach ($unusedTags as $tag) { + foreach ($container->findUnusedTags() as $tag) { // skip whitelisted tags if (in_array($tag, $this->whitelist)) { continue; } + // check for typos $candidates = array(); foreach ($tags as $definedTag) { if ($definedTag === $tag) { continue; } + if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= strlen($tag) / 3) { $candidates[] = $definedTag; } } $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)) { $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); } + $compiler->addLogMessage($formatter->format($this, $message)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 1cdf83df5d..3a96f71e11 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -90,9 +90,9 @@ class FrameworkBundle extends Bundle $container->addCompilerPass(new TranslationDumperPass()); $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new SerializerPass()); - $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); if ($container->getParameter('kernel.debug')) { + $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new ConfigCachePass()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php new file mode 100644 index 0000000000..f354007bb9 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php @@ -0,0 +1,52 @@ + + * + * 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); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php b/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php index 6bd6161ceb..db208fa0d6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php @@ -20,7 +20,7 @@ class LoggingFormatter { 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) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index ca8a136d25..e3a6ea744c 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -91,7 +91,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface private $expressionLanguageProviders = array(); /** - * @var array with tag names used by findTaggedServiceIds + * @var string[] with tag names used by findTaggedServiceIds */ 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() { - $tags = array_values(array_diff($this->findTags(), $this->usedTags)); - $tags = array_unique($tags); - - return $tags; + return array_values(array_diff($this->findTags(), $this->usedTags)); } public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)