[VarDumper] Dumping exceptions is now more compact
This commit is contained in:
parent
695549fdde
commit
19e9cbecbe
@ -20,8 +20,11 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
*/
|
||||
class EnumStub extends Stub
|
||||
{
|
||||
public function __construct(array $values)
|
||||
public $dumpKeys = true;
|
||||
|
||||
public function __construct(array $values, $dumpKeys = true)
|
||||
{
|
||||
$this->value = $values;
|
||||
$this->dumpKeys = $dumpKeys;
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class ExceptionCaster
|
||||
$stub->class = '';
|
||||
$stub->handle = 0;
|
||||
$frames = $trace->value;
|
||||
$prefix = Caster::PREFIX_VIRTUAL;
|
||||
|
||||
$a = array();
|
||||
$j = count($frames);
|
||||
@ -98,33 +99,35 @@ class ExceptionCaster
|
||||
return array();
|
||||
}
|
||||
$lastCall = isset($frames[$i]['function']) ? ' ==> '.(isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
|
||||
$frames[] = array('function' => '');
|
||||
|
||||
for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
|
||||
$call = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[$i]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '???';
|
||||
$f = $frames[$i];
|
||||
$call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'].'()' : '???';
|
||||
|
||||
$a[Caster::PREFIX_VIRTUAL.$j.'. '.$call.$lastCall] = new FrameStub(
|
||||
$label = $call.$lastCall;
|
||||
$frame = new FrameStub(
|
||||
array(
|
||||
'object' => isset($frames[$i]['object']) ? $frames[$i]['object'] : null,
|
||||
'class' => isset($frames[$i]['class']) ? $frames[$i]['class'] : null,
|
||||
'type' => isset($frames[$i]['type']) ? $frames[$i]['type'] : null,
|
||||
'function' => isset($frames[$i]['function']) ? $frames[$i]['function'] : null,
|
||||
'object' => isset($f['object']) ? $f['object'] : null,
|
||||
'class' => isset($f['class']) ? $f['class'] : null,
|
||||
'type' => isset($f['type']) ? $f['type'] : null,
|
||||
'function' => isset($f['function']) ? $f['function'] : null,
|
||||
) + $frames[$i - 1],
|
||||
$trace->keepArgs,
|
||||
true
|
||||
);
|
||||
$f = self::castFrameStub($frame, array(), $frame, true);
|
||||
if (isset($f[$prefix.'src'])) {
|
||||
foreach ($f[$prefix.'src']->value as $label => $frame) {
|
||||
}
|
||||
if (isset($f[$prefix.'args']) && $frame instanceof EnumStub) {
|
||||
$frame->value['args'] = $f[$prefix.'args'];
|
||||
}
|
||||
}
|
||||
$a[$prefix.$j.'. '.$label] = $frame;
|
||||
|
||||
$lastCall = ' ==> '.$call;
|
||||
}
|
||||
$a[Caster::PREFIX_VIRTUAL.$j.'. {main}'.$lastCall] = new FrameStub(
|
||||
array(
|
||||
'object' => null,
|
||||
'class' => null,
|
||||
'type' => null,
|
||||
'function' => '{main}',
|
||||
) + $frames[$i - 1],
|
||||
$trace->keepArgs,
|
||||
true
|
||||
);
|
||||
if (null !== $trace->sliceLength) {
|
||||
$a = array_slice($a, 0, $trace->sliceLength, true);
|
||||
}
|
||||
@ -145,9 +148,8 @@ class ExceptionCaster
|
||||
$f['file'] = substr($f['file'], 0, -strlen($match[0]));
|
||||
$f['line'] = (int) $match[1];
|
||||
}
|
||||
$src = array();
|
||||
if (file_exists($f['file']) && 0 <= self::$srcContext) {
|
||||
$src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
|
||||
|
||||
if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) {
|
||||
$template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem()));
|
||||
|
||||
@ -156,11 +158,14 @@ class ExceptionCaster
|
||||
$templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
|
||||
$templateInfo = $template->getDebugInfo();
|
||||
if (isset($templateInfo[$f['line']])) {
|
||||
$src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
|
||||
$src[$templateName] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
|
||||
}
|
||||
} catch (\Twig_Error_Loader $e) {
|
||||
}
|
||||
}
|
||||
if (!$src) {
|
||||
$src[$f['file']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
|
||||
}
|
||||
} else {
|
||||
$src[$f['file']] = $f['line'];
|
||||
}
|
||||
@ -177,7 +182,7 @@ class ExceptionCaster
|
||||
}
|
||||
}
|
||||
if ($frame->keepArgs && isset($f['args'])) {
|
||||
$a[$prefix.'args'] = $f['args'];
|
||||
$a[$prefix.'args'] = new EnumStub($f['args'], false);
|
||||
}
|
||||
|
||||
return $a;
|
||||
@ -232,12 +237,23 @@ class ExceptionCaster
|
||||
++$ltrim;
|
||||
} while (0 > $i && null !== $pad);
|
||||
|
||||
if (--$ltrim) {
|
||||
foreach ($src as $i => $line) {
|
||||
$src[$i] = isset($line[$ltrim]) && "\r" !== $line[$ltrim] ? substr($line, $ltrim) : ltrim($line, " \t");
|
||||
--$ltrim;
|
||||
|
||||
$pad = strlen($line + $srcContext);
|
||||
$srcArray = array();
|
||||
|
||||
foreach ($src as $i => $c) {
|
||||
if ($ltrim) {
|
||||
$c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
|
||||
}
|
||||
$c = substr($c, 0, -1);
|
||||
$c = new ConstStub($c, $c);
|
||||
if ($i !== $srcContext) {
|
||||
$c->class = 'default';
|
||||
}
|
||||
$srcArray[sprintf("% {$pad}d", $i + $line - $srcContext)] = $c;
|
||||
}
|
||||
|
||||
return implode('', $src);
|
||||
return new EnumStub($srcArray);
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class StubCaster
|
||||
public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
|
||||
{
|
||||
if ($isNested) {
|
||||
$stub->class = '';
|
||||
$stub->class = $c->dumpKeys ? '' : null;
|
||||
$stub->handle = 0;
|
||||
$stub->value = null;
|
||||
$stub->cut = $c->cut;
|
||||
|
@ -162,7 +162,7 @@ class Data
|
||||
$withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
|
||||
$dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
|
||||
if ($withChildren) {
|
||||
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type);
|
||||
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
|
||||
} elseif ($children && 0 <= $cut) {
|
||||
$cut += count($children);
|
||||
}
|
||||
@ -191,10 +191,11 @@ class Data
|
||||
* @param array $children The children to dump
|
||||
* @param int $hashCut The number of items removed from the original hash
|
||||
* @param string $hashType A Cursor::HASH_* const
|
||||
* @param bool $dumpKeys Whether keys should be dumped or not
|
||||
*
|
||||
* @return int The final number of removed items
|
||||
*/
|
||||
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType)
|
||||
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType, $dumpKeys)
|
||||
{
|
||||
$cursor = clone $parentCursor;
|
||||
++$cursor->depth;
|
||||
@ -204,7 +205,7 @@ class Data
|
||||
$cursor->hashCut = $hashCut;
|
||||
foreach ($children as $key => $child) {
|
||||
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
|
||||
$cursor->hashKey = $key;
|
||||
$cursor->hashKey = $dumpKeys ? $key : null;
|
||||
$this->dumpItem($dumper, $cursor, $refs, $child);
|
||||
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
|
||||
$parentCursor->stop = true;
|
||||
|
@ -115,6 +115,10 @@ class CliDumper extends AbstractDumper
|
||||
$attr = array();
|
||||
|
||||
switch ($type) {
|
||||
case 'default':
|
||||
$style = 'default';
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
$style = 'num';
|
||||
break;
|
||||
|
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||
|
||||
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
|
||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||
|
||||
class ExceptionCasterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use VarDumperTestTrait;
|
||||
|
||||
private function getTestException()
|
||||
{
|
||||
return new \Exception('foo');
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
ExceptionCaster::$srcContext = 1;
|
||||
ExceptionCaster::$traceArgs = true;
|
||||
}
|
||||
|
||||
public function testDefaultSettings()
|
||||
{
|
||||
$e = $this->getTestException(1);
|
||||
|
||||
$expectedDump = <<<'EODUMP'
|
||||
Exception {
|
||||
#message: "foo"
|
||||
#code: 0
|
||||
#file: "%sExceptionCasterTest.php"
|
||||
#line: 23
|
||||
-trace: {
|
||||
%d. %sExceptionCasterTest.php: {
|
||||
22: {
|
||||
23: return new \Exception('foo');
|
||||
24: }
|
||||
}
|
||||
%d. %sExceptionCasterTest.php: {
|
||||
%d: {
|
||||
%d: $e = $this->getTestException(1);
|
||||
%d:
|
||||
args: {
|
||||
1
|
||||
}
|
||||
}
|
||||
%A
|
||||
EODUMP;
|
||||
|
||||
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||
}
|
||||
|
||||
public function testNoArgs()
|
||||
{
|
||||
$e = $this->getTestException(1);
|
||||
ExceptionCaster::$traceArgs = false;
|
||||
|
||||
$expectedDump = <<<'EODUMP'
|
||||
Exception {
|
||||
#message: "foo"
|
||||
#code: 0
|
||||
#file: "%sExceptionCasterTest.php"
|
||||
#line: 23
|
||||
-trace: {
|
||||
%d. %sExceptionCasterTest.php: {
|
||||
22: {
|
||||
23: return new \Exception('foo');
|
||||
24: }
|
||||
}
|
||||
%d. %sExceptionCasterTest.php: {
|
||||
%d: {
|
||||
%d: $e = $this->getTestException(1);
|
||||
%d: ExceptionCaster::$traceArgs = false;
|
||||
}
|
||||
%A
|
||||
EODUMP;
|
||||
|
||||
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||
}
|
||||
|
||||
public function testNoSrcContext()
|
||||
{
|
||||
$e = $this->getTestException(1);
|
||||
ExceptionCaster::$srcContext = -1;
|
||||
|
||||
$expectedDump = <<<'EODUMP'
|
||||
Exception {
|
||||
#message: "foo"
|
||||
#code: 0
|
||||
#file: "%sExceptionCasterTest.php"
|
||||
#line: 23
|
||||
-trace: {
|
||||
%d. %sExceptionCasterTest.php: 23
|
||||
%d. %sExceptionCasterTest.php: %d
|
||||
%A
|
||||
EODUMP;
|
||||
|
||||
$this->assertDumpMatchesFormat($expectedDump, $e);
|
||||
}
|
||||
}
|
@ -156,11 +156,11 @@ Generator {
|
||||
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
||||
executing: {
|
||||
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): {
|
||||
%sGeneratorDemo.php:14: """
|
||||
{\n
|
||||
yield from bar();\n
|
||||
}\n
|
||||
"""
|
||||
%sGeneratorDemo.php: {
|
||||
13: {
|
||||
14: yield from bar();
|
||||
15: }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,43 +177,31 @@ array:2 [
|
||||
0 => ReflectionGenerator {
|
||||
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
|
||||
trace: {
|
||||
3. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() ==> yield(): {
|
||||
src: {
|
||||
%sGeneratorDemo.php:9: """
|
||||
{\n
|
||||
yield 1;\n
|
||||
}\n
|
||||
"""
|
||||
}
|
||||
3. %sGeneratorDemo.php: {
|
||||
8: {
|
||||
9: yield 1;
|
||||
10: }
|
||||
}
|
||||
2. Symfony\Component\VarDumper\Tests\Fixtures\bar() ==> Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
|
||||
src: {
|
||||
%sGeneratorDemo.php:20: """
|
||||
{\n
|
||||
yield from GeneratorDemo::foo();\n
|
||||
}\n
|
||||
"""
|
||||
}
|
||||
2. %sGeneratorDemo.php: {
|
||||
19: {
|
||||
20: yield from GeneratorDemo::foo();
|
||||
21: }
|
||||
}
|
||||
1. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() ==> Symfony\Component\VarDumper\Tests\Fixtures\bar(): {
|
||||
src: {
|
||||
%sGeneratorDemo.php:14: """
|
||||
{\n
|
||||
yield from bar();\n
|
||||
}\n
|
||||
"""
|
||||
}
|
||||
1. %sGeneratorDemo.php: {
|
||||
13: {
|
||||
14: yield from bar();
|
||||
15: }
|
||||
}
|
||||
}
|
||||
}
|
||||
1 => Generator {
|
||||
executing: {
|
||||
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
|
||||
%sGeneratorDemo.php:10: """
|
||||
yield 1;\n
|
||||
}\n
|
||||
\n
|
||||
"""
|
||||
%sGeneratorDemo.php: {
|
||||
9: yield 1;
|
||||
10: }
|
||||
11:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,15 +264,14 @@ EOTXT
|
||||
|
||||
if (method_exists($twig, 'getSource')) {
|
||||
$twig = <<<EOTXT
|
||||
foo.twig:2: """
|
||||
foo bar\\n
|
||||
twig source\\n
|
||||
\\n
|
||||
"""
|
||||
|
||||
foo.twig: {
|
||||
1: foo bar
|
||||
2: twig source
|
||||
3:
|
||||
}
|
||||
EOTXT;
|
||||
} else {
|
||||
$twig = '';
|
||||
$twig = '%A';
|
||||
}
|
||||
|
||||
$r = defined('HHVM_VERSION') ? '' : '#%d';
|
||||
@ -289,50 +288,26 @@ stream resource {@{$ref}
|
||||
⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
|
||||
#message: "Unexpected Exception thrown from a caster: Foobar"
|
||||
-trace: {
|
||||
%d. __TwigTemplate_VarDumperFixture_u75a09->doDisplay() ==> new Exception(): {
|
||||
src: {
|
||||
%sTwig.php:19: """
|
||||
// line 2\\n
|
||||
throw new \Exception('Foobar');\\n
|
||||
}\\n
|
||||
"""
|
||||
{$twig} }
|
||||
%d. {$twig}
|
||||
%d. %sTemplate.php: {
|
||||
%d: try {
|
||||
%d: \$this->doDisplay(\$context, \$blocks);
|
||||
%d: } catch (Twig_Error \$e) {
|
||||
}
|
||||
%d. Twig_Template->displayWithErrorHandling() ==> __TwigTemplate_VarDumperFixture_u75a09->doDisplay(): {
|
||||
src: {
|
||||
%sTemplate.php:%d: """
|
||||
try {\\n
|
||||
\$this->doDisplay(\$context, \$blocks);\\n
|
||||
} catch (Twig_Error \$e) {\\n
|
||||
"""
|
||||
}
|
||||
%d. %sTemplate.php: {
|
||||
%d: {
|
||||
%d: \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));
|
||||
%d: }
|
||||
}
|
||||
%d. Twig_Template->display() ==> Twig_Template->displayWithErrorHandling(): {
|
||||
src: {
|
||||
%sTemplate.php:%d: """
|
||||
{\\n
|
||||
\$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));\\n
|
||||
}\\n
|
||||
"""
|
||||
}
|
||||
%d. %sTemplate.php: {
|
||||
%d: try {
|
||||
%d: \$this->display(\$context);
|
||||
%d: } catch (Exception \$e) {
|
||||
}
|
||||
%d. Twig_Template->render() ==> Twig_Template->display(): {
|
||||
src: {
|
||||
%sTemplate.php:%d: """
|
||||
try {\\n
|
||||
\$this->display(\$context);\\n
|
||||
} catch (Exception \$e) {\\n
|
||||
"""
|
||||
}
|
||||
}
|
||||
%d. %slosure%s() ==> Twig_Template->render(): {
|
||||
src: {
|
||||
%sCliDumperTest.php:{$line}: """
|
||||
}\\n
|
||||
};'),\\n
|
||||
));\\n
|
||||
"""
|
||||
}
|
||||
%d. %sCliDumperTest.php: {
|
||||
%d: }
|
||||
{$line}: };'),
|
||||
%d: ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user