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

Skip to content

Commit 08e6214

Browse files
author
Florian Pfitzer
committed
[FrameworkBundle], [DependencyInjection] added logging of unused tags during container compilation
1 parent eb1e3c3 commit 08e6214

File tree

4 files changed

+122
-1
lines changed

4 files changed

+122
-1
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 an 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 = 'Tag "'.$tag.'" was defined on the service(s) '.implode(",", $services).', but was never used.';
80+
if (!empty($candidates)) {
81+
$message .= ' Did you mean "'.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
@@ -27,6 +27,7 @@
2727
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
2828
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass;
2929
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
30+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
3031
use Symfony\Component\DependencyInjection\ContainerBuilder;
3132
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
3233
use Symfony\Component\DependencyInjection\Scope;
@@ -81,6 +82,7 @@ public function build(ContainerBuilder $container)
8182
$container->addCompilerPass(new TranslationDumperPass());
8283
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
8384
$container->addCompilerPass(new SerializerPass());
85+
$container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
8486

8587
if ($container->getParameter('kernel.debug')) {
8688
$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
@@ -84,6 +84,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
8484
*/
8585
private $expressionLanguage;
8686

87+
/**
88+
* @var array with tag names used by findTaggedServiceIds
89+
*/
90+
private $usedTags = array();
91+
8792
/**
8893
* Sets the track resources flag.
8994
*
@@ -1031,6 +1036,7 @@ public function resolveServices($value)
10311036
*/
10321037
public function findTaggedServiceIds($name)
10331038
{
1039+
$this->usedTags[] = $name;
10341040
$tags = array();
10351041
foreach ($this->getDefinitions() as $id => $definition) {
10361042
if ($definition->hasTag($name)) {
@@ -1056,6 +1062,19 @@ public function findTags()
10561062
return array_unique($tags);
10571063
}
10581064

1065+
/**
1066+
* Returns all tags not queried by findTaggedServiceIds
1067+
*
1068+
* @return array An array of tags
1069+
*/
1070+
public function findUnusedTags()
1071+
{
1072+
$tags = array_values(array_diff($this->findTags(), $this->usedTags));
1073+
array_unique($tags);
1074+
1075+
return $tags;
1076+
}
1077+
10591078
/**
10601079
* Returns the Service Conditionals.
10611080
*

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,25 @@ public function testfindTaggedServiceIds()
486486
'foo' => array(
487487
array('foo' => 'foo'),
488488
array('foofoo' => 'foofoo'),
489-
)
489+
),
490490
), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
491491
$this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
492492
}
493493

494+
public function testFindUnusedTags()
495+
{
496+
$builder = new ContainerBuilder();
497+
$builder
498+
->register('foo', 'Bar\FooClass')
499+
->addTag('kernel.event_listener', array('foo' => 'foo'))
500+
->addTag('kenrel.event_listener', array('bar' => 'bar'))
501+
;
502+
$builder->findTaggedServiceIds('kernel.event_listener');
503+
$this->assertEquals($builder->findUnusedTags(), array(
504+
'kenrel.event_listener',
505+
), '->findUnusedTags() returns an array with unused tags');
506+
}
507+
494508
/**
495509
* @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition
496510
*/

0 commit comments

Comments
 (0)