Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9731815

Browse files
[VarDumper] add link to source next to class names
1 parent ccd4bbe commit 9731815

File tree

12 files changed

+76
-40
lines changed

12 files changed

+76
-40
lines changed

src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public function load(array $configs, ContainerBuilder $container)
4343
->addMethodCall('setMinDepth', [$config['min_depth']])
4444
->addMethodCall('setMaxString', [$config['max_string_length']]);
4545

46+
if (method_exists(ReflectionClass::class, 'unsetClosureFileInfo')) {
47+
$container->getDefinition('var_dumper.cloner')
48+
->addMethodCall('addCasters', ReflectionClass::UNSET_CLOSURE_FILE_INFO)
49+
}
50+
4651
if (method_exists(HtmlDumper::class, 'setTheme') && 'dark' !== $config['theme']) {
4752
$container->getDefinition('var_dumper.html_dumper')
4853
->addMethodCall('setTheme', [$config['theme']]);

src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\HttpKernel\DataCollector;
1313

1414
use Symfony\Component\VarDumper\Caster\CutStub;
15+
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
1516
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
1617
use Symfony\Component\VarDumper\Cloner\Data;
1718
use Symfony\Component\VarDumper\Cloner\Stub;
@@ -79,7 +80,7 @@ protected function cloneVar($var)
7980
*/
8081
protected function getCasters()
8182
{
82-
return [
83+
$casters = [
8384
'*' => function ($v, array $a, Stub $s, $isNested) {
8485
if (!$v instanceof Stub) {
8586
foreach ($a as $k => $v) {
@@ -92,5 +93,11 @@ protected function getCasters()
9293
return $a;
9394
},
9495
];
96+
97+
if (method_exists(ReflectionCaster::class, 'unsetClosureFileInfo')) {
98+
$casters += ReflectionCaster::UNSET_CLOSURE_FILE_INFO;
99+
}
100+
101+
return $caster;
95102
}
96103
}

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,17 @@ 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-
}
9992

100-
return [
93+
if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) {
94+
$this->fileLinkFormat = [
10195
$request->getSchemeAndHttpHost().$request->getBasePath().$this->urlFormat,
10296
$this->baseDir.\DIRECTORY_SEPARATOR, '',
10397
];
10498
}
10599
}
100+
101+
return $this->fileLinkFormat;
106102
}
107103
}

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: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
*/
2121
class ReflectionCaster
2222
{
23+
const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo'];
24+
2325
private static $extraMap = [
2426
'docComment' => 'getDocComment',
2527
'extension' => 'getExtensionName',
@@ -46,22 +48,34 @@ public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested,
4648

4749
$stub->class .= self::getSignature($a);
4850

51+
if ($f = $c->getFileName()) {
52+
$stub->attr['file'] = $f;
53+
$stub->attr['line'] = $c->getStartLine();
54+
}
55+
56+
unset($a[$prefix.'parameters']);
57+
4958
if ($filter & Caster::EXCLUDE_VERBOSE) {
5059
$stub->cut += ($c->getFileName() ? 2 : 0) + \count($a);
5160

5261
return [];
5362
}
5463

55-
unset($a[$prefix.'parameters']);
56-
57-
if ($f = $c->getFileName()) {
64+
if ($f) {
5865
$a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
5966
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
6067
}
6168

6269
return $a;
6370
}
6471

72+
public static function unsetClosureFileInfo(\Closure $c, array $a)
73+
{
74+
unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']);
75+
76+
return $a;
77+
}
78+
6579
public static function castGenerator(\Generator $c, array $a, Stub $stub, $isNested)
6680
{
6781
if (!class_exists('ReflectionGenerator', false)) {

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/ContextProvider/RequestContextProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\VarDumper\Dumper\ContextProvider;
1313

1414
use Symfony\Component\HttpFoundation\RequestStack;
15+
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
1516
use Symfony\Component\VarDumper\Cloner\VarCloner;
1617

1718
/**
@@ -29,6 +30,7 @@ public function __construct(RequestStack $requestStack)
2930
$this->requestStack = $requestStack;
3031
$this->cloner = new VarCloner();
3132
$this->cloner->setMaxItems(0);
33+
$this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
3234
}
3335

3436
public function getContext(): ?array

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'])) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public function testClosureCasterExcludingVerbosity()
114114
{
115115
$var = function &($a = 5) {};
116116

117-
$this->assertDumpEquals('Closure&($a = 5) { …6}', $var, Caster::EXCLUDE_VERBOSE);
117+
$this->assertDumpEquals('Closure&($a = 5) { …5}', $var, Caster::EXCLUDE_VERBOSE);
118118
}
119119

120120
public function testReflectionParameter()

src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ public function testCaster()
411411
[position] => 1
412412
[attr] => Array
413413
(
414+
[file] => %a%eVarClonerTest.php
415+
[line] => 20
414416
)
415417
416418
)

src/Symfony/Component/VarDumper/VarDumper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\VarDumper;
1313

14+
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
1415
use Symfony\Component\VarDumper\Cloner\VarCloner;
1516
use Symfony\Component\VarDumper\Dumper\CliDumper;
1617
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
@@ -29,6 +30,7 @@ public static function dump($var)
2930
{
3031
if (null === self::$handler) {
3132
$cloner = new VarCloner();
33+
$cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
3234

3335
if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {
3436
$dumper = 'html' === $_SERVER['VAR_DUMPER_FORMAT'] ? new HtmlDumper() : new CliDumper();

0 commit comments

Comments
 (0)