Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 415f068

Browse files
author
Florian Pfitzer
committed
[FrameworkBundle], [DependencyInjection] added logging of unused tags during container compilation
1 parent d913101 commit 415f068

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
17+
/**
18+
* Find all service tags which are defined, but not used and yield a warning log message.
19+
*
20+
* @author Florian Pfitzer <[email protected]>
21+
*/
22+
class UnusedTagsPass implements CompilerPassInterface
23+
{
24+
/**
25+
* whitelisted tags
26+
*
27+
* @var array
28+
*/
29+
protected $whitelist = array(
30+
"console.command",
31+
"data_collector",
32+
"form.type",
33+
"form.type_extension",
34+
"form.type_guesser",
35+
"kernel.cache_clearer",
36+
"kernel.cache_warmer",
37+
"kernel.event_listener",
38+
"kernel.event_subscriber",
39+
"kernel.fragment_renderer",
40+
"monolog.logger",
41+
"routing.loader",
42+
"security.remember_me_aware",
43+
"security.voter",
44+
"serializer.encoder",
45+
"templating.helper",
46+
"translation.dumper",
47+
"translation.extractor",
48+
"translation.loader",
49+
"twig.extension",
50+
"twig.loader",
51+
"validator.constraint_validator",
52+
"validator.initializer",
53+
);
54+
55+
public function process(ContainerBuilder $container)
56+
{
57+
$compiler = $container->getCompiler();
58+
$formatter = $compiler->getLoggingFormatter();
59+
$tags = $container->findTags();
60+
61+
$unusedTags = $container->findUnusedTags();
62+
foreach ($unusedTags as $tag) {
63+
// skip whitelisted tags
64+
if (in_array($tag, $this->whitelist)) {
65+
continue;
66+
}
67+
// check for typos
68+
$candidates = array();
69+
foreach ($tags as $definedTag) {
70+
if ($definedTag === $tag) {
71+
continue;
72+
}
73+
if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= strlen($tag) / 3) {
74+
$candidates[] = $definedTag;
75+
}
76+
}
77+
78+
$services = array_keys($container->findTaggedServiceIds($tag));
79+
$message = sprintf('Tag "%s" was defined on the service(s) %s, but was never used.', $tag, implode(',', $services));
80+
if (!empty($candidates)) {
81+
$message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates));
82+
}
83+
$compiler->addLogMessage($formatter->format($this, $message));
84+
}
85+
}
86+
}

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
3131
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass;
3232
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
33+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
3334
use Symfony\Component\Debug\ErrorHandler;
3435
use Symfony\Component\DependencyInjection\ContainerBuilder;
3536
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@@ -90,6 +91,7 @@ public function build(ContainerBuilder $container)
9091
$container->addCompilerPass(new TranslationDumperPass());
9192
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
9293
$container->addCompilerPass(new SerializerPass());
94+
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
9395

9496
if ($container->getParameter('kernel.debug')) {
9597
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
9090
*/
9191
private $expressionLanguageProviders = array();
9292

93+
/**
94+
* @var array with tag names used by findTaggedServiceIds
95+
*/
96+
private $usedTags = array();
97+
9398
/**
9499
* Sets the track resources flag.
95100
*
@@ -1045,6 +1050,7 @@ public function resolveServices($value)
10451050
*/
10461051
public function findTaggedServiceIds($name)
10471052
{
1053+
$this->usedTags[] = $name;
10481054
$tags = array();
10491055
foreach ($this->getDefinitions() as $id => $definition) {
10501056
if ($definition->hasTag($name)) {
@@ -1070,6 +1076,19 @@ public function findTags()
10701076
return array_unique($tags);
10711077
}
10721078

1079+
/**
1080+
* Returns all tags not queried by findTaggedServiceIds
1081+
*
1082+
* @return array An array of tags
1083+
*/
1084+
public function findUnusedTags()
1085+
{
1086+
$tags = array_values(array_diff($this->findTags(), $this->usedTags));
1087+
$tags = array_unique($tags);
1088+
1089+
return $tags;
1090+
}
1091+
10731092
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
10741093
{
10751094
$this->expressionLanguageProviders[] = $provider;

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,18 @@ public function testfindTaggedServiceIds()
508508
$this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
509509
}
510510

511+
public function testFindUnusedTags()
512+
{
513+
$builder = new ContainerBuilder();
514+
$builder
515+
->register('foo', 'Bar\FooClass')
516+
->addTag('kernel.event_listener', array('foo' => 'foo'))
517+
->addTag('kenrel.event_listener', array('bar' => 'bar'))
518+
;
519+
$builder->findTaggedServiceIds('kernel.event_listener');
520+
$this->assertEquals(array('kenrel.event_listener'), $builder->findUnusedTags(), '->findUnusedTags() returns an array with unused tags');
521+
}
522+
511523
/**
512524
* @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition
513525
*/

0 commit comments

Comments
 (0)