[DX] [TwigBundle] Improve default expand states of exception template

This commit is contained in:
Niels Keurentjes 2017-04-07 17:28:24 +02:00 committed by Fabien Potencier
parent f04c0b5f04
commit df25691250
7 changed files with 62 additions and 23 deletions

View File

@ -30,6 +30,14 @@
<div class="sf-tabs">
<div class="tab">
{% set exception_as_array = exception.toarray %}
{% set _exceptions_with_user_code = [] %}
{% for i, e in exception_as_array %}
{% for trace in e.trace %}
{% if (trace.file is not empty) and ('/vendor/' not in trace.file) and ('/var/cache/' not in trace.file) and not loop.last %}
{% set _exceptions_with_user_code = _exceptions_with_user_code|merge([i]) %}
{% endif %}
{% endfor %}
{% endfor %}
<h3 class="tab-title">
{% if exception_as_array|length > 1 %}
Exceptions <span class="badge">{{ exception_as_array|length }}</span>
@ -39,8 +47,8 @@
</h3>
<div class="tab-content">
{% for e in exception_as_array %}
{{ include('@Twig/Exception/traces.html.twig', { exception: e, index: loop.index }, with_context = false) }}
{% for i, e in exception_as_array %}
{{ include('@Twig/Exception/traces.html.twig', { exception: e, index: loop.index, expand: i in _exceptions_with_user_code or (_exceptions_with_user_code is empty and loop.first) }, with_context = false) }}
{% endfor %}
</div>
</div>

View File

@ -2,7 +2,7 @@
<table class="trace-details">
<thead class="trace-head">
<tr>
<th class="sf-toggle" data-toggle-selector="#trace-html-{{ index }}" data-toggle-initial="{{ 1 == index ? 'display' }}">
<th class="sf-toggle" data-toggle-selector="#trace-html-{{ index }}" data-toggle-initial="{{ expand ? 'display' }}">
<h3 class="trace-class">
<span class="trace-namespace">
{{ exception.class|split('\\')|slice(0, -1)|join('\\') }}
@ -24,7 +24,7 @@
<tbody id="trace-html-{{ index }}" class="sf-toggle-content">
{% set _is_first_user_code = true %}
{% for i, trace in exception.trace %}
{% set _display_code_snippet = _is_first_user_code and ('/vendor/' not in trace.file) %}
{% set _display_code_snippet = _is_first_user_code and ('/vendor/' not in trace.file) and ('/var/cache/' not in trace.file) and (trace.file is not empty) %}
{% if _display_code_snippet %}{% set _is_first_user_code = false %}{% endif %}
<tr>
<td class="trace-line {{ trace.file|default(false) ? 'sf-toggle' }}" data-toggle-selector="#trace-html-{{ index }}-{{ i }}" data-toggle-initial="{{ _display_code_snippet ? 'display' }}">

View File

@ -439,27 +439,30 @@ class AutowirePass extends AbstractRecursivePass
private function createTypeAlternatives($type)
{
$message = ' This type-hint could be aliased to ';
if (isset($this->ambiguousServiceTypes[$type])) {
$message .= sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
$message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
} elseif (isset($this->types[$type])) {
$message .= sprintf('the existing "%s" service', $this->types[$type]);
$message = sprintf('the existing "%s" service', $this->types[$type]);
} else {
return;
}
$message = sprintf(' You should maybe alias this %s to %s', class_exists($type, false) ? 'class' : 'interface', $message);
$aliases = array();
foreach (class_parents($type) + class_implements($type) as $parent) {
if ($this->container->has($parent)) {
if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
$aliases[] = $parent;
}
}
if (1 < count($aliases)) {
$message .= sprintf('; or be updated to one of the following: "%s"', implode('", "', $aliases));
if (1 < $len = count($aliases)) {
$message .= '; or type-hint against one of its parents: ';
for ($i = 0, --$len; $i < $len; ++$i) {
$message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
}
$message .= sprintf('or %s "%s"', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
} elseif ($aliases) {
$message .= sprintf('; or be updated to "%s"', $aliases[0]);
$message .= sprintf('; or type-hint against %s "%s" instead', class_exists($aliases[0], false) ? 'class' : 'interface', $aliases[0]);
}
return $message.'.';

View File

@ -59,7 +59,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. This type-hint could be aliased to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service.
* @expectedExceptionMessage Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service.
*/
public function testProcessAutowireParent()
{
@ -78,7 +78,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. This type-hint could be aliased to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service.
* @expectedExceptionMessage Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service.
*/
public function testProcessAutowireInterface()
{
@ -133,7 +133,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. This type-hint could be aliased to one of these existing services: "c1", "c2", "c3".
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2", "c3".
*/
public function testTypeCollision()
{
@ -151,7 +151,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. This type-hint could be aliased to one of these existing services: "a1", "a2".
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
*/
public function testTypeNotGuessable()
{
@ -168,7 +168,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. This type-hint could be aliased to one of these existing services: "a1", "a2".
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
*/
public function testTypeNotGuessableWithSubclass()
{
@ -334,7 +334,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. This type-hint could be aliased to the existing "foo" service.
* @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service.
*/
public function testDontUseAbstractServices()
{
@ -587,7 +587,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. This type-hint could be aliased to one of these existing services: "c1", "c2".
* @expectedExceptionMessage Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2".
*/
public function testSetterInjectionCollisionThrowsException()
{
@ -604,7 +604,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. This type-hint could be aliased to the existing "foo" service.
* @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service.
*/
public function testProcessDoesNotTriggerDeprecations()
{
@ -688,7 +688,7 @@ class AutowirePassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. This type-hint could be aliased to the existing "i" service; or be updated to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface".
* @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to the existing "i" service; or type-hint against interface "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
*/
public function testByIdAlternative()
{

View File

@ -4,6 +4,8 @@ CHANGELOG
3.3.0
-----
* Added `kernel.project_dir` and `Kernel::getProjectDir()`
* Deprecated `kernel.root_dir` and `Kernel::getRootDir()`
* Deprecated `Kernel::getEnvParameters()`
* Deprecated the special `SYMFONY__` environment variables
* added the possibility to change the query string parameter used by `UriSigner`

View File

@ -59,6 +59,8 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
private $projectDir;
const VERSION = '3.3.0-DEV';
const VERSION_ID = 30300;
const MAJOR_VERSION = 3;
@ -80,6 +82,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
$this->environment = $environment;
$this->debug = (bool) $debug;
$this->rootDir = $this->getRootDir();
$this->projectDir = $this->getProjectDir();
$this->name = $this->getName();
if ($this->debug) {
@ -306,6 +309,28 @@ abstract class Kernel implements KernelInterface, TerminableInterface
return $this->rootDir;
}
/**
* Gets the application root dir (path of the project's composer file).
*
* @return string The project root dir
*/
public function getProjectDir()
{
if (null === $this->projectDir) {
$r = new \ReflectionObject($this);
$dir = $rootDir = dirname($r->getFileName());
while (!file_exists($dir.'/composer.json')) {
if ($dir === dirname($dir)) {
return $this->projectDir = $rootDir;
}
$dir = dirname($dir);
}
$this->projectDir = $dir;
}
return $this->projectDir;
}
/**
* {@inheritdoc}
*/
@ -559,6 +584,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
return array_merge(
array(
'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
'kernel.project_dir' => realpath($this->projectDir) ?: $this->projectDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,

View File

@ -121,9 +121,9 @@ interface KernelInterface extends HttpKernelInterface, \Serializable
public function isDebug();
/**
* Gets the application root dir.
* Gets the application root dir (path of the project's Kernel class).
*
* @return string The application root dir
* @return string The Kernel root dir
*/
public function getRootDir();