8000 [VarDumper] Handle attributes in Data clones for more semantic dumps · symfony/symfony@0e1814f · GitHub
[go: up one dir, main page]

Skip to content

Commit 0e1814f

Browse files
[VarDumper] Handle attributes in Data clones for more semantic dumps
1 parent b835ab1 commit 0e1814f

File tree

12 files changed

+177
-86
lines changed

12 files changed

+177
-86
lines changed

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,11 @@ table.logs .sf-call-stack abbr {
912912
#collector-content .sf-dump .trace li.selected {
913913
background: rgba(255, 255, 153, 0.5);
914914
}
915+
#collector-content .sf-dump-expanded code { color: #222; }
916+
#collector-content .sf-dump-expanded code .sf-dump-const {
917+
background: rgba(255, 255, 153, 0.5);
918+
font-weight: normal;
919+
}
915920

916921
{# Search Results page
917922
========================================================================= #}

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

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is
8989
$stub->handle = 0;
9090
$frames = $trace->value;
9191
$prefix = Caster::PREFIX_VIRTUAL;
92-
$format = "\0~Stack level %s.\0%s";
9392

9493
$a = array();
9594
$j = count($frames);
@@ -99,14 +98,14 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is
9998
if (!isset($trace->value[$i])) {
10099
return array();
101100
}
102-
$lastCall = isset($frames[$i]['function']) ? ' ==> '.(isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
101+
$lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
103102
$frames[] = array('function' => '');
104103

105104
for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
106105
$f = $frames[$i];
107106
$call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'].'()' : '???';
108107

109-
$label = $call.$lastCall;
108+
$label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall;
110109
$frame = new FrameStub(
111110
array(
112111
'object' => isset($f['object']) ? $f['object'] : null,
@@ -120,14 +119,15 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is
120119
$f = self::castFrameStub($frame, array(), $frame, true);
121120
if (isset($f[$prefix.'src'])) {
122121
foreach ($f[$prefix.'src']->value as $label => $frame) {
122+
$label = substr_replace($label, "title=Stack level $j.&", 2, 0);
123123
}
124124
if (isset($f[$prefix.'args']) && $frame instanceof EnumStub) {
125125
$frame->value['args'] = $f[$prefix.'args'];
126126
}
127127
}
128-
$a[sprintf($format, $j, $label)] = $frame;
128+
$a[$label] = $frame;
129129

130-
$lastCall = ' ==> '.$call;
130+
$lastCall = $call;
131131
}
132132
if (null !== $trace->sliceLength) {
133133
$a = array_slice($a, 0, $trace->sliceLength, true);
@@ -149,28 +149,38 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is
149149
$f['file'] = substr($f['file'], 0, -strlen($match[0]));
150150
$f['line'] = (int) $match[1];
151151
}
152-
$src = array();
152+
$caller = isset($f['function']) ? sprintf('in %s() on line %d', (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'], $f['line']) : null;
153+
$src = $f['line'];
154+
$srcKey = $f['file'];
155+
$ellipsis = explode(DIRECTORY_SEPARATOR, $srcKey);
156+
$ellipsis = 3 < count($ellipsis) ? 2 + strlen(implode(array_slice($ellipsis, -2))) : 0;
157+
153158
if (file_exists($f['file']) && 0 <= self::$srcContext) {
154159
if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) {
155160
$template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem()));
156161

157162
try {
163+
$ellipsis = 0;
158164
$templateName = $template->getTemplateName();
159165
$templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName));
160166
$templateInfo = $template->getDebugInfo();
161167
if (isset($templateInfo[$f['line']])) {
162-
$src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext);
168+
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, $caller, 'twig');
169+
$srcKey = $templateName.':'.$templateInfo[$f['line']];
163170
}
164171
} catch (\Twig_Error_Loader $e) {
165172
}
166173
}
167-
if (!$src) {
168-
$src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext);
174+
if ($srcKey == $f['file']) {
175+
$src = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext, $caller, 'php', $f['file']);
176+
$srcKey .= ':'.$f['line'];
177+
if ($ellipsis) {
178+
$ellipsis += 1 + strlen($f['line']);
179+
}
169180
}
170-
} else {
171-
$src[$f['file']] = $f['line'];
172181
}
173-
$a[$prefix.'src'] = new EnumStub($src);
182+
$srcAttr = $ellipsis ? 'ellipsis='.$ellipsis : '';
183+
$a[$prefix.'src'] = new EnumStub(array("\0~$srcAttr\0$srcKey" => $src));
174184
}
175185

176186
unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);
@@ -214,7 +224,7 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte
214224
return $a;
215225
}
216226

217-
private static function extractSource(array $srcArray, $line, $srcContext)
227+
private static function extractSource(array $srcArray, $line, $srcContext, $title, $lang, $file = null)
218228
{
219229
$src = array();
220230

@@ -239,20 +249,24 @@ private static function extractSource(array $srcArray, $line, $srcContext)
239249
} while (0 > $i && null !== $pad);
240250

241251
--$ltrim;
242-
243-
$pad = strlen($line + $srcContext);
244252
$srcArray = array();
245253

246254
foreach ($src as $i => $c) {
247255
if ($ltrim) {
248256
$c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
249257
}
250258
$c = substr($c, 0, -1);
251-
$c = new ConstStub($c, $c);
252259
if ($i !== $srcContext) {
253-
$c->class = 'default';
260+
$c = new ConstStub('default', $c);
261+
} else {
262+
$c = new ConstStub($c, $title);
263+
if (null !== $file) {
264+
$c->attr['file'] = $file;
265+
$c->attr['line'] = $line;
266+
}
254267
}
255-
$srcArray[sprintf("% {$pad}d", $i + $line - $srcContext)] = $c;
268+
$c->attr['lang'] = $lang;
269+
$srcArray[sprintf("\0~%d\0", $i + $line - $srcContext)] = $c;
256270
}
257271

258272
return new EnumStub($srcArray);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public static function castStub(Stub $c, array $a, Stub $stub, $isNested)
2828
$stub->value = $c->value;
2929
$stub->handle = $c->handle;
3030
$stub->cut = $c->cut;
31+
$stub->attr = $c->attr;
3132

3233
return array();
3334
}
@@ -56,6 +57,7 @@ public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested)
5657
$stub->handle = 0;
5758
$stub->value = null;
5859
$stub->cut = $c->cut;
60+
$stub->attr = $c->attr;
5961

6062
$a = array();
6163

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

Expand all lines: src/Symfony/Component/VarDumper/Cloner/Cursor.php
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ class Cursor
3838
public $hashLength = 0;
3939
public $hashCut = 0;
4040
public $stop = false;
41+
public $attr = array();
4142
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item)
155155
$firstSeen = true;
156156

157157
if (!$item instanceof Stub) {
158+
$cursor->attr = array();
158159
$type = gettype($item);
159160
} elseif (Stub::TYPE_REF === $item->type) {
160161
if ($item->handle) {
@@ -167,6 +168,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item)
167168
$cursor->hardRefHandle = $this->useRefHandles & $item->handle;
168169
$cursor->hardRefCount = $item->refCount;
169170
}
171+
$cursor->attr = $item->attr;
170172
$type = $item->class ?: gettype($item->value);
171173
$item = $item->value;
172174
}
@@ -181,6 +183,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item)
181183
}
182184
$cursor->softRefHandle = $this->useRefHandles & $item->handle;
183185
$cursor->softRefCount = $item->refCount;
186+
$cursor->attr = $item->attr;
184187
$cut = $item->cut;
185188

186189
if ($item->position && $firstSeen) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ class Stub
3737
public $handle = 0;
3838
public $refCount = 0;
3939
public $position = 0;
40+
public $attr = array();
4041
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public function dumpScalar(Cursor $cursor, $type, $value)
112112
$this->dumpKey($cursor);
113113

114114
$style = 'const';
115-
$attr = array();
115+
$attr = $cursor->attr;
116116

117117
switch ($type) {
118118
case 'default':
@@ -148,7 +148,7 @@ public function dumpScalar(Cursor $cursor, $type, $value)
148148
break;
149149

150150
default:
151-
$attr['value'] = isset($value[0]) && !preg_match('//u', $value) ? $this->utf8Encode($value) : $value;
151+
$attr += array('value' => isset($value[0]) && !preg_match('//u', $value) ? $this->utf8Encode($value) : $value);
152152
$value = isset($type[0]) && !preg_match('//u', $type) ? $this->utf8Encode($type) : $type;
153153
break;
154154
}
@@ -164,6 +164,7 @@ public function dumpScalar(Cursor $cursor, $type, $value)
164164
public function dumpString(Cursor $cursor, $str, $bin, $cut)
165165
{
166166
$this->dumpKey($cursor);
167+
$attr = $cursor->attr;
167168

168169
if ($bin) {
169170
$str = $this->utf8Encode($str);
@@ -172,7 +173,7 @@ public function dumpString(Cursor $cursor, $str, $bin, $cut)
172173
$this->line .= '""';
173174
$this->dumpLine($cursor->depth, true);
174175
} else {
175-
$attr = array(
176+
$attr += array(
176177
'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,
177178
'binary' => $bin,
178179
);
@@ -350,7 +351,8 @@ protected function dumpKey(Cursor $cursor)
350351
case '~':
351352
$style = 'meta';
352353
if (isset($key[0][1])) {
353-
$attr['title'] = substr($key[0], 1);
354+
parse_str(substr($key[0], 1), $attr);
355+
$attr += array('binary' => $cursor->hashKeyIsBinary);
354356
}
355357
break;
356358
case '*':

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

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ class HtmlDumper extends CliDumper
4343
'meta' => 'color:#B729D9',
4444
'key' => 'color:#56DB3A',
4545
'index' => 'color:#1299DA',
46+
'expanded code.hljs' => 'display:inline; padding:0; background:none',
4647
);
4748

4849
private $displayOptions = array(
4950
'maxDepth' => 1,
5051
'maxStringLength' => 160,
52+
'fileLinkFormat' => null,
5153
);
5254
private $extraDisplayOptions = array();
5355

@@ -184,6 +186,19 @@ function toggle(a, recursive) {
184186
return function (root, x) {
185187
root = doc.getElementById(root);
186188
189+
var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
190+
options = {$options},
191+
elt = root.getElementsByTagName('A'),
192+
len = elt.length,
193+
i = 0, s, h,
194+
t = [];
195+
196+
while (i < len) t.push(elt[i++]);
197+
198+
for (i in x) {
199+
options[i] = x[i];
200+
}
201+
187202
function a(e, f) {
188203
addEventListener(root, e, function (e) {
189204
if ('A' == e.target.tagName) {
@@ -201,6 +216,20 @@ function isCtrlKey(e) {
201216
refStyle.innerHTML = '';
202217
}
203218
});
219+
if (options.fileLinkFormat) {
220+
addEventListener(root, 'click', function (e) {
221+
e = e.target;
222+
while (root != e && 'CODE' != e.tagName) {
223+
e = e.parentNode;
224+
}
225+
if ('CODE' == e.tagName) {
226+
var f = e.getAttribute('data-file'), l = e.getAttribute('data-line');
227+
if (f && l) {
228+
location.href = options.fileLinkFormat.replace('%f', f).replace('%l', l);
229+
}
230+
}
231+
});
232+
}
204233
a('mouseover', function (a) {
205234
if (a = idRx.exec(a.className)) {
206235
try {
@@ -246,19 +275,6 @@ function isCtrlKey(e) {
246275
}
247276
});
248277
249-
var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
250-
options = {$options},
251-
elt = root.getElementsByTagName('A'),
252-
len = elt.length,
253-
i = 0, s, h,
254-
t = [];
255-
256-
while (i < len) t.push(elt[i++]);
257-
258-
for (i in x) {
259-
options[i] = x[i];
260-
}
261-
262278
elt = root.getElementsByTagName('SAMP');
263279
len = elt.length;
264280
i = 0;
@@ -369,6 +385,15 @@ function isCtrlKey(e) {
369385
border: 0;
370386
outline: none;
371387
}
388+
pre.sf-dump .sf-dump-ellipsis {
389+
display: inline-block;
390+
overflow: visible;
391+
text-overflow: ellipsis;
392+
width: 50px;
393+
white-space: nowrap;
394+
overflow: hidden;
395+
vertical-align: top;
396+
}
372397
.sf-dump-str-collapse .sf-dump-str-collapse {
373398
display: none;
374399
}
@@ -452,6 +477,11 @@ protected function style($style, $value, $attr = array())
452477
} elseif ('private' === $style) {
453478
$style .= sprintf(' title="Private property defined in class:&#10;`%s`"', esc($attr['class']));
454479
}
480+
if (isset($attr['ellipsis'])) {
481+
$label = esc(substr($value, -$attr['ellipsis']));
482+
483+
return sprintf('<span class=sf-dump-%s><abbr title="%s" class=sf-dump-ellipsis>%2$s</abbr>%s</span>', $style, substr($v, 0, -strlen($label)), $label);
484+
}
455485

456486
$map = static::$controlCharsMap;
457487
$style = "<span class=sf-dump-{$style}>";
@@ -475,6 +505,13 @@ protected function style($style, $value, $attr = array())
475505
} else {
476506
$v .= '</span>';
477507
}
508+
if (isset($attr['lang'])) {
509+
if (isset($attr['file'], $attr['line'])) {
510+
$v = sprintf('<code class="%s" data-file="%s" data-line="%d">%s</code>', esc($attr['lang']), esc($attr['file']), $attr['line'], $v);
511+
} else {
512+
$v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v);
513+
}
514+
}
478515

479516
return $v;
480517
}

0 commit comments

Comments
 (0)
0