From 0229e5c216cd0b926b8a54dfebe23f885606fb63 Mon Sep 17 00:00:00 2001 From: mwos Date: Fri, 22 Oct 2021 14:41:12 +0200 Subject: [PATCH] [VarDumper] Fix dumping twig templates found in exceptions --- .../VarDumper/Caster/ExceptionCaster.php | 30 +++++---- .../Tests/Caster/ExceptionCasterTest.php | 62 +++++++++++++------ .../VarDumper/Tests/Fixtures/Twig.php | 17 ++++- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index c29b7df261d33..f2c0f96872fdd 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -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']]; + } } } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 50c7a8d24dca0..10cf512776096 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -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 { @@ -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; @@ -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; @@ -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; @@ -114,9 +117,9 @@ 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; @@ -124,6 +127,30 @@ public function testNoSrcContext() $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')) { @@ -146,10 +173,10 @@ public function testHtmlDump() #code: 0 #file: "%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php" - #line: 28 + #line: %d trace: { %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:28 +Stack level %d.">%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:%d …%d } } @@ -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__), ]), @@ -186,7 +213,7 @@ public function testFrameWithTwig() class: "__TwigTemplate_VarDumperFixture_u75a09" src: { %sTwig.php:1 { - › + ›%s › foo bar › twig source } @@ -201,12 +228,11 @@ class: "__TwigTemplate_VarDumperFixture_u75a09" %sExceptionCasterTest.php:2 { › foo bar › twig source - › + ›%s } } } ] - EODUMP; $this->assertDumpMatchesFormat($expectedDump, $f); @@ -221,7 +247,7 @@ public function testExcludeVerbosity() #message: "foo" #code: 0 #file: "%sExceptionCasterTest.php" - #line: 28 + #line: %d } EODUMP; diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php index 8b84d820fcf7c..5d1a73d424b4b 100644 --- a/src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/Twig.php @@ -1,7 +1,20 @@ createError(); + } +} + /* foo.twig */ -class __TwigTemplate_VarDumperFixture_u75a09 extends Twig\Template +class __TwigTemplate_VarDumperFixture_u75a09 extends AbstractTwigTemplate { private $path; @@ -28,7 +41,7 @@ public function getTemplateName() public function getDebugInfo() { - return [20 => 1, 21 => 2]; + return [33 => 1, 34 => 2]; } public function getSourceContext()