Skip to content

Commit

Permalink
[VarDumper] Fix dumping twig templates found in exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
event15 authored and nicolas-grekas committed Oct 25, 2021
1 parent 2a50705 commit 52d5b02
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 32 deletions.
30 changes: 18 additions & 12 deletions Caster/ExceptionCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,18 +214,24 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is

if (file_exists($f['file']) && 0 <= self::$srcContext) {
if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
$template = $f['object'] ?? unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));

$ellipsis = 0;
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
$templateInfo = $template->getDebugInfo();
if (isset($templateInfo[$f['line']])) {
if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
$templatePath = null;
}
if ($templateSrc) {
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
$srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
$template = null;
if (isset($f['object'])) {
$template = $f['object'];
} elseif ((new \ReflectionClass($f['class']))->isInstantiable()) {
$template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
}
if (null !== $template) {
$ellipsis = 0;
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
$templateInfo = $template->getDebugInfo();
if (isset($templateInfo[$f['line']])) {
if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
$templatePath = null;
}
if ($templateSrc) {
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
$srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
}
}
}
}
Expand Down
62 changes: 44 additions & 18 deletions Tests/Caster/ExceptionCasterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
use Symfony\Component\VarDumper\Caster\FrameStub;
use Symfony\Component\VarDumper\Caster\TraceStub;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
use Symfony\Component\VarDumper\Tests\Fixtures\DumpClassWithErrors;

class ExceptionCasterTest extends TestCase
{
Expand All @@ -44,15 +47,15 @@ public function testDefaultSettings()
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 28
#line: %d
trace: {
%s%eTests%eCaster%eExceptionCasterTest.php:28 {
%s%eTests%eCaster%eExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
%s%eTests%eCaster%eExceptionCasterTest.php:40 { …}
%s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;

Expand All @@ -66,13 +69,13 @@ public function testSeek()

$expectedDump = <<<'EODUMP'
{
%s%eTests%eCaster%eExceptionCasterTest.php:28 {
%s%eTests%eCaster%eExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
%s%eTests%eCaster%eExceptionCasterTest.php:65 { …}
%s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;

Expand All @@ -89,15 +92,15 @@ public function testNoArgs()
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 28
#line: %d
trace: {
%sExceptionCasterTest.php:28 {
%sExceptionCasterTest.php:%d {
Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestException($msg, &$ref = null)
› {
› return new \Exception(''.$msg);
› }
}
%s%eTests%eCaster%eExceptionCasterTest.php:84 { …}
%s%eTests%eCaster%eExceptionCasterTest.php:%d { …}
%A
EODUMP;

Expand All @@ -114,16 +117,40 @@ public function testNoSrcContext()
#message: "1"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 28
#line: %d
trace: {
%s%eTests%eCaster%eExceptionCasterTest.php:28
%s%eTests%eCaster%eExceptionCasterTest.php:%d
%s%eTests%eCaster%eExceptionCasterTest.php:%d
%A
EODUMP;

$this->assertDumpMatchesFormat($expectedDump, $e);
}

public function testShouldReturnTraceForConcreteTwigWithError()
{
require_once \dirname(__DIR__).'/Fixtures/Twig.php';

$innerExc = (new \__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__))->provideError();
$nestingWrapper = new \stdClass();
$nestingWrapper->trace = new TraceStub($innerExc->getTrace());

$expectedDump = <<<'EODUMP'
{
+"trace": {
%sTwig.php:%d {
AbstractTwigTemplate->provideError()
› {
› return $this->createError();
› }
}
%sExceptionCasterTest.php:%d { …}
%A
EODUMP;

$this->assertDumpMatchesFormat($expectedDump, $nestingWrapper);
}

public function testHtmlDump()
{
if (ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {
Expand All @@ -146,10 +173,10 @@ public function testHtmlDump()
#<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span>
#<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%sExceptionCasterTest.php
%d characters"><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%e</span>Tests%eCaster%eExceptionCasterTest.php</span>"
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>28</span>
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>%d</span>
<span class=sf-dump-meta>trace</span>: {<samp>
<span class=sf-dump-meta title="%sExceptionCasterTest.php
Stack level %d."><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%e</span>Tests%eCaster%eExceptionCasterTest.php</span>:<span class=sf-dump-num>28</span>
Stack level %d."><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%e</span>Tests%eCaster%eExceptionCasterTest.php</span>:<span class=sf-dump-num>%d</span>
&hellip;%d
</samp>}
</samp>}
Expand All @@ -169,12 +196,12 @@ public function testFrameWithTwig()
$f = [
new FrameStub([
'file' => \dirname(__DIR__).'/Fixtures/Twig.php',
'line' => 20,
'line' => 33,
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
]),
new FrameStub([
'file' => \dirname(__DIR__).'/Fixtures/Twig.php',
'line' => 21,
'line' => 34,
'class' => '__TwigTemplate_VarDumperFixture_u75a09',
'object' => new \__TwigTemplate_VarDumperFixture_u75a09(null, __FILE__),
]),
Expand All @@ -186,7 +213,7 @@ public function testFrameWithTwig()
class: "__TwigTemplate_VarDumperFixture_u75a09"
src: {
%sTwig.php:1 {
%s
› foo bar
› twig source
}
Expand All @@ -201,12 +228,11 @@ class: "__TwigTemplate_VarDumperFixture_u75a09"
%sExceptionCasterTest.php:2 {
› foo bar
› twig source
%s
}
}
}
]

EODUMP;

$this->assertDumpMatchesFormat($expectedDump, $f);
Expand All @@ -221,7 +247,7 @@ public function testExcludeVerbosity()
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 28
#line: %d
}
EODUMP;

Expand Down
17 changes: 15 additions & 2 deletions Tests/Fixtures/Twig.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
<?php

abstract class AbstractTwigTemplate extends Twig\Template
{
private function createError()
{
return new \RuntimeException('Manually triggered error.');
}

public function provideError()
{
return $this->createError();
}
}

/* foo.twig */
class __TwigTemplate_VarDumperFixture_u75a09 extends Twig\Template
class __TwigTemplate_VarDumperFixture_u75a09 extends AbstractTwigTemplate
{
private $path;

Expand All @@ -28,7 +41,7 @@ public function getTemplateName()

public function getDebugInfo()
{
return [20 => 1, 21 => 2];
return [33 => 1, 34 => 2];
}

public function getSourceContext()
Expand Down

0 comments on commit 52d5b02

Please sign in to comment.