瀏覽代碼

Merge remote branch 'schmittjoh/diLogging'

* schmittjoh/diLogging:
  [DependencyInjection] enable debug related passes only in debug environment
  [DependencyInjection] removed pass time
  [DependencyInjection] fixes a bug which might have occurred when using property injection under certain circumstances
  [DependencyInjection] fixed method name
  [FrameworkBundle] whitespace fix
  [DependencyInjection] refactored code a bit, added some more logging messages
  [DependencyInjection] dump a readable format
  [DependencyInjection] better logging
Fabien Potencier 14 年之前
父節點
當前提交
0b563c32ac

+ 24 - 0
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+class CompilerDebugDumpPass implements CompilerPassInterface
+{
+    public function process(ContainerBuilder $container)
+    {
+        $cache = new ConfigCache($this->getCompilerLogFilename($container), false);
+        $cache->write(implode("\n", $container->getCompiler()->getLog()));
+    }
+
+    public static function getCompilerLogFilename(ContainerInterface $container)
+    {
+        $class = $container->getParameter('kernel.container_class');
+
+        return $container->getParameter('kernel.cache_dir').'/'.$class.'Compiler.log';
+    }
+}

+ 6 - 1
src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

@@ -22,6 +22,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddClassesToAuto
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass;
 use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CompilerDebugDumpPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
 use Symfony\Component\DependencyInjection\Scope;
@@ -81,6 +82,10 @@ class FrameworkBundle extends Bundle
         $container->addCompilerPass(new AddClassesToAutoloadMapPass());
         $container->addCompilerPass(new TranslatorPass());
         $container->addCompilerPass(new AddCacheWarmerPass());
-        $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING);
+
+        if ($container->getParameter('kernel.debug')) {
+            $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING);
+            $container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
+        }
     }
 }

+ 16 - 27
src/Symfony/Component/DependencyInjection/Compiler/Compiler.php

@@ -22,9 +22,8 @@ use Symfony\Component\DependencyInjection\Compiler\PassConfig;
 class Compiler
 {
     private $passConfig;
-    private $currentPass;
-    private $currentStartTime;
     private $log;
+    private $loggingFormatter;
     private $serviceReferenceGraph;
 
     /**
@@ -34,6 +33,7 @@ class Compiler
     {
         $this->passConfig = new PassConfig();
         $this->serviceReferenceGraph = new ServiceReferenceGraph();
+        $this->loggingFormatter = new LoggingFormatter();
         $this->log = array();
     }
 
@@ -57,6 +57,16 @@ class Compiler
         return $this->serviceReferenceGraph;
     }
 
+    /**
+     * Returns the logging formatter which can be used by compilation passes.
+     *
+     * @return LoggingFormatter
+     */
+    public function getLoggingFormatter()
+    {
+        return $this->loggingFormatter;
+    }
+
     /**
      * Adds a pass to the PassConfig.
      *
@@ -71,7 +81,7 @@ class Compiler
     /**
      * Adds a log message.
      *
-     * @param string $string The log message 
+     * @param string $string The log message
      */
     public function addLogMessage($string)
     {
@@ -91,36 +101,15 @@ class Compiler
     /**
      * Run the Compiler and process all Passes.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function compile(ContainerBuilder $container)
     {
+        $start = microtime(true);
         foreach ($this->passConfig->getPasses() as $pass) {
-            $this->startPass($pass);
             $pass->process($container);
-            $this->endPass($pass);
         }
-    }
 
-    /**
-     * Starts an individual pass.
-     *
-     * @param CompilerPassInterface $pass The pass to start
-     */
-    private function startPass(CompilerPassInterface $pass)
-    {
-        $this->currentPass = $pass;
-        $this->currentStartTime = microtime(true);
-    }
-
-    /**
-     * Ends an individual pass.
-     *
-     * @param CompilerPassInterface $pass The compiler pass
-     */
-    private function endPass(CompilerPassInterface $pass)
-    {
-        $this->currentPass = null;
-        $this->addLogMessage(sprintf('%s finished in %.3fs', get_class($pass), microtime(true) - $this->currentStartTime));
+        $this->addLogMessage(sprintf('Compilation finished in %.3fs.', microtime(true) - $start));
     }
 }

+ 11 - 2
src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

@@ -25,6 +25,9 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
 {
     private $repeatedPass;
     private $graph;
+    private $compiler;
+    private $formatter;
+    private $currentId;
 
     /**
      * {@inheritDoc}
@@ -41,9 +44,13 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        $this->graph = $container->getCompiler()->getServiceReferenceGraph();
+        $this->compiler = $container->getCompiler();
+        $this->formatter = $this->compiler->getLoggingFormatter();
+        $this->graph = $this->compiler->getServiceReferenceGraph();
+
+        foreach ($container->getDefinitions() as $id => $definition) {
+            $this->currentId = $id;
 
-        foreach ($container->getDefinitions() as $definition) {
             $definition->setArguments(
                 $this->inlineArguments($container, $definition->getArguments())
             );
@@ -75,6 +82,8 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
                 }
 
                 if ($this->isInlinableDefinition($container, $id, $definition = $container->getDefinition($id))) {
+                    $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId));
+
                     if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) {
                         $arguments[$k] = $definition;
                     } else {

+ 38 - 0
src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * Used to format logging messages during the compilation.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class LoggingFormatter
+{
+    public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
+    {
+        return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason));
+    }
+
+    public function formatInlineService(CompilerPassInterface $pass, $id, $target)
+    {
+        return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target));
+    }
+
+    public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId)
+    {
+        return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId));
+    }
+
+    public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId)
+    {
+        return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
+    }
+
+    public function format(CompilerPassInterface $pass, $message)
+    {
+        return sprintf('%s: %s', get_class($pass), $message);
+    }
+}

+ 5 - 1
src/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php

@@ -13,13 +13,17 @@ class RemoveAbstractDefinitionsPass implements CompilerPassInterface
     /**
      * Removes abstract definitions from the ContainerBuilder
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
+        $compiler = $container->getCompiler();
+        $formatter = $compiler->getLoggingFormatter();
+
         foreach ($container->getDefinitions() as $id => $definition) {
             if ($definition->isAbstract()) {
                 $container->remove($id);
+                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract'));
             }
         }
     }

+ 5 - 1
src/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php

@@ -25,16 +25,20 @@ class RemovePrivateAliasesPass implements CompilerPassInterface
     /**
      * Removes private aliases from the ContainerBuilder
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
+        $compiler = $container->getCompiler();
+        $formatter = $compiler->getLoggingFormatter();
+
         foreach ($container->getAliases() as $id => $alias) {
             if ($alias->isPublic()) {
                 continue;
             }
 
             $container->removeAlias($id);
+            $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias'));
         }
     }
 }

+ 6 - 2
src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php

@@ -36,12 +36,14 @@ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
     /**
      * Processes the ContainerBuilder to remove unused definitions.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      * @return void
      */
     public function process(ContainerBuilder $container)
     {
-        $graph = $container->getCompiler()->getServiceReferenceGraph();
+        $compiler = $container->getCompiler();
+        $formatter = $compiler->getLoggingFormatter();
+        $graph = $compiler->getServiceReferenceGraph();
 
         $hasChanged = false;
         foreach ($container->getDefinitions() as $id => $definition) {
@@ -71,8 +73,10 @@ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
                 $container->setDefinition((string) reset($referencingAliases), $definition);
                 $definition->setPublic(true);
                 $container->remove($id);
+                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases)));
             } else if (0 === count($referencingAliases) && false === $isReferenced) {
                 $container->remove($id);
+                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused'));
                 $hasChanged = true;
             }
         }

+ 16 - 2
src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php

@@ -22,13 +22,20 @@ use Symfony\Component\DependencyInjection\Reference;
  */
 class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
 {
+    private $compiler;
+    private $formatter;
+    private $sourceId;
+
     /**
      * Process the Container to replace aliases with service definitions.
      *
-     * @param ContainerBuilder $container 
+     * @param ContainerBuilder $container
      */
     public function process(ContainerBuilder $container)
     {
+        $this->compiler = $container->getCompiler();
+        $this->formatter = $this->compiler->getLoggingFormatter();
+
         foreach ($container->getAliases() as $id => $alias) {
             $aliasId = (string) $alias;
 
@@ -67,7 +74,9 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
             }
         }
 
-        foreach ($container->getDefinitions() as $definition) {
+        foreach ($container->getDefinitions() as $id => $definition) {
+            $this->sourceId = $id;
+
             $definition->setArguments(
                 $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
             );
@@ -75,6 +84,10 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
             $definition->setMethodCalls(
                 $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
             );
+
+            $definition->setProperties(
+                $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
+            );
         }
     }
 
@@ -93,6 +106,7 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
             } else if ($argument instanceof Reference) {
                 if ($currentId === (string) $argument) {
                     $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
+                    $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId));
                 }
             }
         }

+ 6 - 0
src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

@@ -15,6 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
 class ResolveDefinitionTemplatesPass implements CompilerPassInterface
 {
     private $container;
+    private $compiler;
+    private $formatter;
 
     /**
      * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
@@ -24,6 +26,9 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
     public function process(ContainerBuilder $container)
     {
         $this->container = $container;
+        $this->compiler = $container->getCompiler();
+        $this->formatter = $this->compiler->getLoggingFormatter();
+
         foreach (array_keys($container->getDefinitions()) as $id) {
             // yes, we are specifically fetching the definition from the
             // container to ensure we are not operating on stale data
@@ -54,6 +59,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
             $parentDef = $this->resolveDefinition($parent, $parentDef);
         }
 
+        $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent));
         $def = new Definition();
 
         // merge in parent definition