Skip to content

Commit ffc52fb

Browse files
[VarDumper] add link to source next to class names
1 parent 87a223b commit ffc52fb

File tree

14 files changed

+56
-65
lines changed

14 files changed

+56
-65
lines changed

src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,12 @@ private function normalizeAndSortOptionsColumns(array $options)
184184
private function getDumpFunction()
185185
{
186186
$cloner = new VarCloner();
187-
$cloner->addCasters(['Closure' => function ($c, $a) {
187+
$cloner->addCasters(['Closure' => function ($c, $a, $s) {
188188
$prefix = Caster::PREFIX_VIRTUAL;
189189

190190
return [
191-
$prefix.'file' => $a[$prefix.'file'],
192-
$prefix.'line' => $a[$prefix.'line'],
191+
$prefix.'file' => $s->attr['file'] ?? $a[$prefix.'file'],
192+
$prefix.'line' => $s->attr['line'] ?? $a[$prefix.'line'],
193193
];
194194
}]);
195195
$dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain
1717
---------------- --------------------%s
1818
Normalizer Closure%s{%w
1919
file: "%s%eExtension%eCore%eType%eChoiceType.php"%w
20-
line: "%s to %s" %s
20+
line: %s
2121
} %s
2222
---------------- --------------------%s
2323

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data)
1010
Closure(s): [ %s
1111
Closure%s{%w
1212
file: "%s%eExtension%eCore%eType%eFormType.php"%w
13-
line: "%s to %s" %s
13+
line: %s
1414
}, %s
1515
Closure%s{%w
1616
file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w
17-
line: "%s to %s" %s
17+
line: %s
1818
} %s
1919
] %s
2020
---------------- ----------------------%s

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo)
1818
---------------- --------------------%s
1919
Normalizer Closure%s{%w
2020
file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php"%w
21-
line: "%s to %s" %s
21+
line: %s
2222
} %s
2323
---------------- --------------------%s
2424

src/Symfony/Component/HttpKernel/Debug/FileLinkFormatter.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,16 @@ public static function generateUrlFormat(UrlGeneratorInterface $router, $routeNa
8787

8888
private function getFileLinkFormat()
8989
{
90-
if ($this->fileLinkFormat) {
91-
return $this->fileLinkFormat;
92-
}
9390
if ($this->requestStack && $this->baseDir && $this->urlFormat) {
9491
$request = $this->requestStack->getMasterRequest();
95-
if ($request instanceof Request) {
96-
if ($this->urlFormat instanceof \Closure && !$this->urlFormat = ($this->urlFormat)()) {
97-
return;
98-
}
99-
100-
return [
92+
if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) {
93+
return $this->fileLinkFormat = [
10194
$request->getSchemeAndHttpHost().$request->getBasePath().$this->urlFormat,
10295
$this->baseDir.\DIRECTORY_SEPARATOR, '',
10396
];
10497
}
10598
}
99+
100+
return $this->fileLinkFormat;
106101
}
107102
}

src/Symfony/Component/HttpKernel/Tests/Debug/FileLinkFormatterTest.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,6 @@ public function testWhenFileLinkFormatAndNoRequest()
3434
$this->assertSame("debug://open?url=file://$file&line=3", $sut->format($file, 3));
3535
}
3636

37-
public function testWhenFileLinkFormatAndRequest()
38-
{
39-
$file = __DIR__.\DIRECTORY_SEPARATOR.'file.php';
40-
$requestStack = new RequestStack();
41-
$request = new Request();
42-
$requestStack->push($request);
43-
44-
$sut = new FileLinkFormatter('debug://open?url=file://%f&line=%l', $requestStack, __DIR__, '/_profiler/open?file=%f&line=%l#line%l');
45-
46-
$this->assertSame("debug://open?url=file://$file&line=3", $sut->format($file, 3));
47-
}
48-
4937
public function testWhenNoFileLinkFormatAndRequest()
5038
{
5139
$file = __DIR__.\DIRECTORY_SEPARATOR.'file.php';

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@ public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested,
4646

4747
$stub->class .= self::getSignature($a);
4848

49+
if ($f = $c->getFileName()) {
50+
$stub->attr['file'] = $f;
51+
$stub->attr['line'] = $c->getStartLine();
52+
}
53+
4954
if ($filter & Caster::EXCLUDE_VERBOSE) {
50-
$stub->cut += ($c->getFileName() ? 2 : 0) + \count($a);
55+
$stub->cut += \count($a);
5156

5257
return [];
5358
}
5459

5560
unset($a[$prefix.'parameters']);
5661

57-
if ($f = $c->getFileName()) {
58-
$a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
59-
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
60-
}
61-
6262
return $a;
6363
}
6464

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ protected function castObject(Stub $stub, $isNested)
279279
$stub->class = get_parent_class($class).'@anonymous';
280280
}
281281
if (isset($this->classInfo[$class])) {
282-
list($i, $parents, $hasDebugInfo) = $this->classInfo[$class];
282+
list($i, $parents, $hasDebugInfo, $fileInfo) = $this->classInfo[$class];
283283
} else {
284284
$i = 2;
285285
$parents = [$class];
@@ -295,9 +295,16 @@ protected function castObject(Stub $stub, $isNested)
295295
}
296296
$parents[] = '*';
297297

298-
$this->classInfo[$class] = [$i, $parents, $hasDebugInfo];
298+
$r = new \ReflectionClass($class);
299+
$fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [
300+
'file' => $r->getFileName(),
301+
'line' => $r->getStartLine(),
302+
];
303+
304+
$this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo];
299305
}
300306

307+
$stub->attr += $fileInfo;
301308
$a = Caster::castObject($obj, $class, $hasDebugInfo);
302309

303310
try {

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ public function dumpString(Cursor $cursor, $str, $bin, $cut)
274274
public function enterHash(Cursor $cursor, $type, $class, $hasChild)
275275
{
276276
$this->dumpKey($cursor);
277+
$attr = $cursor->attr;
277278

278279
if ($this->collapseNextHash) {
279280
$cursor->skipChildren = true;
@@ -282,11 +283,11 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild)
282283

283284
$class = $this->utf8Encode($class);
284285
if (Cursor::HASH_OBJECT === $type) {
285-
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{';
286+
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).' {' : '{';
286287
} elseif (Cursor::HASH_RESOURCE === $type) {
287-
$prefix = $this->style('note', $class.' resource').($hasChild ? ' {' : ' ');
288+
$prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');
288289
} else {
289-
$prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';
290+
$prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class, $attr).' [' : '[';
290291
}
291292

292293
if ($cursor->softRefCount || 0 < $cursor->softRefHandle) {
@@ -454,11 +455,9 @@ protected function style($style, $value, $attr = [])
454455
goto href;
455456
}
456457

457-
$style = $this->styles[$style];
458-
459458
$map = static::$controlCharsMap;
460459
$startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : '';
461-
$endCchr = $this->colors ? "\033[m\033[{$style}m" : '';
460+
$endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : '';
462461
$value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) {
463462
$s = $startCchr;
464463
$c = $c[$i = 0];
@@ -473,7 +472,7 @@ protected function style($style, $value, $attr = [])
473472
if ($cchrCount && "\033" === $value[0]) {
474473
$value = substr($value, \strlen($startCchr));
475474
} else {
476-
$value = "\033[{$style}m".$value;
475+
$value = "\033[{$this->styles[$style]}m".$value;
477476
}
478477
if ($cchrCount && $endCchr === substr($value, -\strlen($endCchr))) {
479478
$value = substr($value, 0, -\strlen($endCchr));
@@ -485,7 +484,11 @@ protected function style($style, $value, $attr = [])
485484
href:
486485
if ($this->colors && $this->handlesHrefGracefully) {
487486
if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) {
488-
$attr['href'] = $href;
487+
if ('note' === $style) {
488+
$value .= "\033]8;;{$href}\033\\^\033]8;;\033\\";
489+
} else {
490+
$attr['href'] = $href;
491+
}
489492
}
490493
if (isset($attr['href'])) {
491494
$value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\";
@@ -632,7 +635,7 @@ private function isWindowsTrueColor()
632635
private function getSourceLink($file, $line)
633636
{
634637
if ($fmt = $this->displayOptions['fileLinkFormat']) {
635-
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
638+
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file);
636639
}
637640

638641
return false;

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,17 @@ function resetHighlightedNodes(root) {
314314
}
315315
316316
function a(e, f) {
317-
addEventListener(root, e, function (e) {
317+
addEventListener(root, e, function (e, n) {
318318
if ('A' == e.target.tagName) {
319319
f(e.target, e);
320320
} else if ('A' == e.target.parentNode.tagName) {
321321
f(e.target.parentNode, e);
322-
} else if (e.target.nextElementSibling && 'A' == e.target.nextElementSibling.tagName) {
323-
f(e.target.nextElementSibling, e, true);
322+
} else if ((n = e.target.nextElementSibling) && 'A' == n.tagName) {
323+
if (!/\bsf-dump-toggle\b/.test(n.className)) {
324+
n = n.nextElementSibling;
325+
}
326+
327+
f(n, e, true);
324328
}
325329
});
326330
};
@@ -852,7 +856,13 @@ protected function style($style, $value, $attr = [])
852856
} elseif ('str' === $style && 1 < $attr['length']) {
853857
$style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
854858
} elseif ('note' === $style && false !== $c = strrpos($v, '\\')) {
855-
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $v, $style, substr($v, $c + 1));
859+
if (isset($attr['file']) && $link = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) {
860+
$link = sprintf('<a href="%s" rel="noopener noreferrer">^</a>', esc($this->utf8Encode($link)));
861+
} else {
862+
$link = '';
863+
}
864+
865+
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>%s', $v, $style, substr($v, $c + 1), $link);
856866
} elseif ('protected' === $style) {
857867
$style .= ' title="Protected property"';
858868
} elseif ('meta' === $style && isset($attr['title'])) {

0 commit comments

Comments
 (0)