Skip to content

Commit 51547b7

Browse files
[VarDumper] Dumping exceptions is now more compact
1 parent 695549f commit 51547b7

File tree

8 files changed

+213
-112
lines changed

8 files changed

+213
-112
lines changed

src/Symfony/Component/VarDumper/Caster/EnumStub.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
*/
2121
class EnumStub extends Stub
2222
{
23-
public function __construct(array $values)
23+
public $dumpKeys = true;
24+
25+
public function __construct(array $values, $dumpKeys = true)
2426
{
2527
$this->value = $values;
28+
$this->dumpKeys = $dumpKeys;
2629
}
2730
}

src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php

+46-25
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is
8888
$stub->class = '';
8989
$stub->handle = 0;
9090
$frames = $trace->value;
91+
$prefix = Caster::PREFIX_VIRTUAL;
9192

9293
$a = array();
9394
$j = count($frames);
@@ -98,33 +99,35 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is
9899
return array();
99100
}
100101
$lastCall = isset($frames[$i]['function']) ? ' ==> '.(isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
102+
$frames[] = array('function' => '');
101103

102104
for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
103-
$call = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[$i]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '???';
105+
$f = $frames[$i];
106+
$call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'].'()' : '???';
104107

105-
$a[Caster::PREFIX_VIRTUAL.$j.'. '.$call.$lastCall] = new FrameStub(
108+
$label = $call.$lastCall;
109+
$frame = new FrameStub(
106110
array(
107-
'object' => isset($frames[$i]['object']) ? $frames[$i]['object'] : null,
108-
'class' => isset($frames[$i]['class']) ? $frames[$i]['class'] : null,
109-
'type' => isset($frames[$i]['type']) ? $frames[$i]['type'] : null,
110-
'function' => isset($frames[$i]['function']) ? $frames[$i]['function'] : null,
111+
'object' => isset($f['object']) ? $f['object'] : null,
112+
'class' => isset($f['class']) ? $f['class'] : null,
113+
'type' => isset($f['type']) ? $f['type'] : null,
114+
'function' => isset($f['function']) ? $f['function'] : null,
111115
) + $frames[$i - 1],
112116
$trace->keepArgs,
113117
true
114118
);
119+
$f = self::castFrameStub($frame, array(), $frame, true);
120+
if (isset($f[$prefix.'src'])) {
121+
foreach ($f[$prefix.'src']->value as $label => $frame) {
122+
}
123+
if (isset($f[$prefix.'args']) && $frame instanceof EnumStub) {
124+
$frame->value['args'] = $f[$prefix.'args'];
125+
}
126+
}
127+
$a[$prefix.$j.'. '.$label] = $frame;
115128

116129
$lastCall = ' ==> '.$call;
117130
}
118-
$a[Caster::PREFIX_VIRTUAL.$j.'. {main}'.$lastCall] = new FrameStub(
119-
array(
120-
'object' => null,
121-
'class' => null,
122-
'type' => null,
123-
'function' => '{main}',
124-
) + $frames[$i - 1],
125-
$trace->keepArgs,
126-
true
127-
);
128131
if (null !== $trace->sliceLength) {
129132
$a = array_slice($a, 0, $trace->sliceLength, true);
130133
}
@@ -145,9 +148,13 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
145148
$f['file'] = substr($f['file'], 0, -strlen($match[0]));
146149
$f['line'] = (int) $match[1];
147150
}
151+
$relFile = $f['file'];
152+
$home = getenv('HOME');
153+
if (false !== $home && 0 === strpos($relFile, $home.DIRECTORY_SEPARATOR)) {
154+
$relFile = '~'.substr($relFile, strlen($home));
155+
}
156+
$src = array();
148157
if (file_exists($f['file']) && 0 <= self::$srcContext) {
149-
$src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
150-
151158
if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) {
152159
$template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem()));
153160

@@ -156,13 +163,16 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
156163
$templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
157164
$templateInfo = $template->getDebugInfo();
158165
if (isset($templateInfo[$f['line']])) {
159-
$src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
166+
$src[$templateName] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
160167
}
161168
} catch (\Twig_Error_Loader $e) {
162169
}
163170
}
171+
if (!$src) {
172+
$src[$relFile] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
173+
}
164174
} else {
165-
$src[$f['file']] = $f['line'];
175+
$src[$relFile] = $f['line'];
166176
}
167177
$a[$prefix.'src'] = new EnumStub($src);
168178
}
@@ -177,7 +187,7 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
177187
}
178188
}
179189
if ($frame->keepArgs && isset($f['args'])) {
180-
$a[$prefix.'args'] = $f['args'];
190+
$a[$prefix.'args'] = new EnumStub($f['args'], false);
181191
}
182192

183193
return $a;
@@ -232,12 +242,23 @@ private static function extractSource(array $srcArray, $line, $srcContext)
232242
++$ltrim;
233243
} while (0 > $i && null !== $pad);
234244

235-
if (--$ltrim) {
236-
foreach ($src as $i => $line) {
237-
$src[$i] = isset($line[$ltrim]) && "\r" !== $line[$ltrim] ? substr($line, $ltrim) : ltrim($line, " \t");
245+
--$ltrim;
246+
247+
$pad = strlen($line + $srcContext);
248+
$srcArray = array();
249+
250+
foreach ($src as $i => $c) {
251+
if ($ltrim) {
252+
$c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
253+
}
254+
$c = substr($c, 0, -1);
255+
$c = new ConstStub($c, $c);
256+
if ($i !== $srcContext) {
257+
$c->class = 'default';
238258
}
259+
$srcArray[sprintf("% {$pad}d", $i + $line - $srcContext)] = $c;
239260
}
240261

241-
return implode('', $src);
262+
return new EnumStub($srcArray);
242263
}
243264
}

src/Symfony/Component/VarDumper/Caster/StubCaster.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static function cutInternals($obj, array $a, Stub $stub, $isNested)
5252
public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
5353
{
5454
if ($isNested) {
55-
$stub->class = '';
55+
$stub->class = $c->dumpKeys ? '' : null;
5656
$stub->handle = 0;
5757
$stub->value = null;
5858
$stub->cut = $c->cut;

src/Symfony/Component/VarDumper/Cloner/Data.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item)
162162
$withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
163163
$dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
164164
if ($withChildren) {
165-
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type);
165+
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
166166
} elseif ($children && 0 <= $cut) {
167167
$cut += count($children);
168168
}
@@ -191,10 +191,11 @@ private function dumpItem($dumper, $cursor, &$refs, $item)
191191
* @param array $children The children to dump
192192
* @param int $hashCut The number of items removed from the original hash
193193
* @param string $hashType A Cursor::HASH_* const
194+
* @param bool $dumpKeys Whether keys should be dumped or not
194195
*
195196
* @return int The final number of removed items
196197
*/
197-
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType)
198+
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType, $dumpKeys)
198199
{
199200
$cursor = clone $parentCursor;
200201
++$cursor->depth;
@@ -204,7 +205,7 @@ private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCu
204205
$cursor->hashCut = $hashCut;
205206
foreach ($children as $key => $child) {
206207
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
207-
$cursor->hashKey = $key;
208+
$cursor->hashKey = $dumpKeys ? $key : null;
208209
$this->dumpItem($dumper, $cursor, $refs, $child);
209210
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
210211
$parentCursor->stop = true;

src/Symfony/Component/VarDumper/Dumper/CliDumper.php

+4
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ public function dumpScalar(Cursor $cursor, $type, $value)
115115
$attr = array();
116116

117117
switch ($type) {
118+
case 'default':
119+
$style = 'default';
120+
break;
121+
118122
case 'integer':
119123
$style = 'num';
120124
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Caster;
13+
14+
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
15+
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
16+
17+
class ExceptionCasterTest extends \PHPUnit_Framework_TestCase
18+
{
19+
use VarDumperTestTrait;
20+
21+
private function getTestException()
22+
{
23+
return new \Exception('foo');
24+
}
25+
26+
protected function tearDown()
27+
{
28+
ExceptionCaster::$srcContext = 1;
29+
ExceptionCaster::$traceArgs = true;
30+
}
31+
32+
public function testDefaultSettings()
33+
{
34+
$e = $this->getTestException(1);
35+
36+
$expectedDump = <<<'EODUMP'
37+
Exception {
38+
#message: "foo"
39+
#code: 0
40+
#file: "%sExceptionCasterTest.php"
41+
#line: 23
42+
-trace: {
43+
%d. %sExceptionCasterTest.php: {
44+
22: {
45+
23: return new \Exception('foo');
46+
24: }
47+
}
48+
%d. %sExceptionCasterTest.php: {
49+
%d: {
50+
%d: $e = $this->getTestException(1);
51+
%d:
52+
args: {
53+
1
54+
}
55+
}
56+
%A
57+
EODUMP;
58+
59+
$this->assertDumpMatchesFormat($expectedDump, $e);
60+
}
61+
62+
public function testNoArgs()
63+
{
64+
$e = $this->getTestException(1);
65+
ExceptionCaster::$traceArgs = false;
66+
67+
$expectedDump = <<<'EODUMP'
68+
Exception {
69+
#message: "foo"
70+
#code: 0
71+
#file: "%sExceptionCasterTest.php"
72+
#line: 23
73+
-trace: {
74+
%d. %sExceptionCasterTest.php: {
75+
22: {
76+
23: return new \Exception('foo');
77+
24: }
78+
}
79+
%d. %sExceptionCasterTest.php: {
80+
%d: {
81+
%d: $e = $this->getTestException(1);
82+
%d: ExceptionCaster::$traceArgs = false;
83+
}
84+
%A
85+
EODUMP;
86+
87+
$this->assertDumpMatchesFormat($expectedDump, $e);
88+
}
89+
90+
public function testNoSrcContext()
91+
{
92+
$e = $this->getTestException(1);
93+
ExceptionCaster::$srcContext = -1;
94+
95+
$expectedDump = <<<'EODUMP'
96+
Exception {
97+
#message: "foo"
98+
#code: 0
99+
#file: "%sExceptionCasterTest.php"
100+
#line: 23
101+
-trace: {
102+
%d. %sExceptionCasterTest.php: 23
103+
%d. %sExceptionCasterTest.php: %d
104+
%A
105+
EODUMP;
106+
107+
$this->assertDumpMatchesFormat($expectedDump, $e);
108+
}
109+
}

src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php

+22-34
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,11 @@ public function testGenerator()
156156
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
157157
executing: {
158158
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): {
159-
%sGeneratorDemo.php:14: """
160-
{\n
161-
yield from bar();\n
162-
}\n
163-
"""
159+
%sGeneratorDemo.php: {
160+
13: {
161+
14: yield from bar();
162+
15: }
163+
}
164164
}
165165
}
166166
}
@@ -177,43 +177,31 @@ public function testGenerator()
177177
0 => ReflectionGenerator {
178178
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
179179
trace: {
180-
3. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() ==> yield(): {
181-
src: {
182-
%sGeneratorDemo.php:9: """
183-
{\n
184-
yield 1;\n
185-
}\n
186-
"""
187-
}
180+
3. %sGeneratorDemo.php: {
181+
8: {
182+
9: yield 1;
183+
10: }
188184
}
189-
2. Symfony\Component\VarDumper\Tests\Fixtures\bar() ==> Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
190-
src: {
191-
%sGeneratorDemo.php:20: """
192-
{\n
193-
yield from GeneratorDemo::foo();\n
194-
}\n
195-
"""
196-
}
185+
2. %sGeneratorDemo.php: {
186+
19: {
187+
20: yield from GeneratorDemo::foo();
188+
21: }
197189
}
198-
1. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() ==> Symfony\Component\VarDumper\Tests\Fixtures\bar(): {
199-
src: {
200-
%sGeneratorDemo.php:14: """
201-
{\n
202-
yield from bar();\n
203-
}\n
204-
"""
205-
}
190+
1. %sGeneratorDemo.php: {
191+
13: {
192+
14: yield from bar();
193+
15: }
206194
}
207195
}
208196
}
209197
1 => Generator {
210198
executing: {
211199
Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): {
212-
%sGeneratorDemo.php:10: """
213-
yield 1;\n
214-
}\n
215-
\n
216-
"""
200+
%sGeneratorDemo.php: {
201+
9: yield 1;
202+
10: }
203+
11:
204+
}
217205
}
218206
}
219207
}

0 commit comments

Comments
 (0)