Skip to content

Commit 5440d67

Browse files
feature #31446 [VarDumper] Output the location of calls to dump() (ktherage)
This PR was merged into the 4.4 branch. Discussion ---------- [VarDumper] Output the location of calls to dump() | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | not tested yet | Fixed tickets | #30830 | License | MIT | Doc PR | see #30830 Commits ------- f0a59d3 [VarDumper] Output the location of calls to dump()
2 parents 55843f2 + f0a59d3 commit 5440d67

File tree

7 files changed

+160
-4
lines changed

7 files changed

+160
-4
lines changed

src/Symfony/Bundle/DebugBundle/Resources/config/services.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@
4040
<argument>0</argument> <!-- flags -->
4141
</service>
4242

43+
<service id="var_dumper.contextualized_cli_dumper" class="Symfony\Component\VarDumper\Dumper\ContextualizedDumper" decorates="var_dumper.cli_dumper">
44+
<argument type="service" id="var_dumper.contextualized_cli_dumper.inner" />
45+
<argument type="collection">
46+
<argument type="service" key="source">
47+
<service class="Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider">
48+
<argument>%kernel.charset%</argument>
49+
<argument type="string">%kernel.project_dir%</argument>
50+
<argument type="service" id="debug.file_link_formatter" on-invalid="null" />
51+
</service>
52+
</argument>
53+
</argument>
54+
</service>
55+
4356
<service id="var_dumper.html_dumper" class="Symfony\Component\VarDumper\Dumper\HtmlDumper">
4457
<argument>null</argument>
4558
<argument>%kernel.charset%</argument>

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

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

1414
use Symfony\Component\VarDumper\Caster\Caster;
15+
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
1516

1617
/**
1718
* @author Nicolas Grekas <p@tchwork.com>
@@ -24,6 +25,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
2425
private $maxDepth = 20;
2526
private $maxItemsPerDepth = -1;
2627
private $useRefHandles = -1;
28+
private $context = [];
2729

2830
/**
2931
* @param array $data An array as returned by ClonerInterface::cloneVar()
@@ -227,6 +229,17 @@ public function withRefHandles($useRefHandles)
227229
return $data;
228230
}
229231

232+
/**
233+
* @return static
234+
*/
235+
public function withContext(array $context)
236+
{
237+
$data = clone $this;
238+
$data->context = $context;
239+
240+
return $data;
241+
}
242+
230243
/**
231244
* Seeks to a specific key in nested data structures.
232245
*
@@ -281,7 +294,18 @@ public function seek($key)
281294
public function dump(DumperInterface $dumper)
282295
{
283296
$refs = [0];
284-
$this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]);
297+
$cursor = new Cursor();
298+
299+
if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) {
300+
$cursor->attr['if_links'] = true;
301+
$cursor->hashType = -1;
302+
$dumper->dumpScalar($cursor, 'default', '^');
303+
$cursor->attr = ['if_links' => true];
304+
$dumper->dumpScalar($cursor, 'default', ' ');
305+
$cursor->hashType = 0;
306+
}
307+
308+
$this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]);
285309
}
286310

287311
/**

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function __construct($output = null, string $charset = null, int $flags =
8383
]);
8484
}
8585

86-
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f';
86+
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';
8787
}
8888

8989
/**
@@ -490,6 +490,8 @@ protected function style($style, $value, $attr = [])
490490
if (isset($attr['href'])) {
491491
$value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\";
492492
}
493+
} elseif ($attr['if_links'] ?? false) {
494+
return '';
493495
}
494496

495497
return $value;
@@ -548,6 +550,10 @@ protected function dumpLine($depth, $endOfValue = false)
548550

549551
protected function endValue(Cursor $cursor)
550552
{
553+
if (-1 === $cursor->hashType) {
554+
return;
555+
}
556+
551557
if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {
552558
if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {
553559
$this->line .= ',';
@@ -628,7 +634,7 @@ private function isWindowsTrueColor(): bool
628634
private function getSourceLink(string $file, int $line)
629635
{
630636
if ($fmt = $this->displayOptions['fileLinkFormat']) {
631-
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file);
637+
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line);
632638
}
633639

634640
return false;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\Dumper;
13+
14+
use Symfony\Component\VarDumper\Cloner\Data;
15+
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
16+
17+
/**
18+
* @author Kévin Thérage <therage.kevin@gmail.com>
19+
*/
20+
class ContextualizedDumper implements DataDumperInterface
21+
{
22+
private $wrappedDumper;
23+
private $contextProviders;
24+
25+
/**
26+
* @param ContextProviderInterface[] $contextProviders
27+
*/
28+
public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders)
29+
{
30+
$this->wrappedDumper = $wrappedDumper;
31+
$this->contextProviders = $contextProviders;
32+
}
33+
34+
public function dump(Data $data)
35+
{
36+
$context = [];
37+
foreach ($this->contextProviders as $contextProvider) {
38+
$context[\get_class($contextProvider)] = $contextProvider->getContext();
39+
}
40+
41+
$this->wrappedDumper->dump($data->withContext($context));
42+
}
43+
}

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public function testMaxIntBoundary()
5353
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
5454
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
5555
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
56+
[context:Symfony\Component\VarDumper\Cloner\Data:private] => Array
57+
(
58+
)
59+
5660
)
5761
5862
EOTXT;
@@ -141,6 +145,10 @@ public function testClone()
141145
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
142146
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
143147
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
148+
[context:Symfony\Component\VarDumper\Cloner\Data:private] => Array
149+
(
150+
)
151+
144152
)
145153
146154
EOTXT;
@@ -309,6 +317,10 @@ public function testLimits()
309317
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
310318
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
311319
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
320+
[context:Symfony\Component\VarDumper\Cloner\Data:private] => Array
321+
(
322+
)
323+
312324
)
313325
314326
EOTXT;
@@ -327,7 +339,7 @@ public function testJsonCast()
327339
$clone = $cloner->cloneVar($data);
328340

329341
$expected = <<<'EOTXT'
330-
object(Symfony\Component\VarDumper\Cloner\Data)#%i (6) {
342+
object(Symfony\Component\VarDumper\Cloner\Data)#%d (7) {
331343
["data":"Symfony\Component\VarDumper\Cloner\Data":private]=>
332344
array(2) {
333345
[0]=>
@@ -372,6 +384,9 @@ public function testJsonCast()
372384
int(-1)
373385
["useRefHandles":"Symfony\Component\VarDumper\Cloner\Data":private]=>
374386
int(-1)
387+
["context":"Symfony\Component\VarDumper\Cloner\Data":private]=>
388+
array(0) {
389+
}
375390
}
376391

377392
EOTXT;
@@ -432,6 +447,10 @@ public function testCaster()
432447
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
433448
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
434449
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
450+
[context:Symfony\Component\VarDumper\Cloner\Data:private] => Array
451+
(
452+
)
453+
435454
)
436455
437456
EOTXT;
@@ -501,6 +520,10 @@ public function testPhp74()
501520
[maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20
502521
[maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1
503522
[useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1
523+
[context:Symfony\Component\VarDumper\Cloner\Data:private] => Array
524+
(
525+
)
526+
504527
)
505528

506529
EOTXT;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\Dumper;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\VarDumper\Cloner\VarCloner;
16+
use Symfony\Component\VarDumper\Dumper\CliDumper;
17+
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
18+
use Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
19+
20+
/**
21+
* @author Kévin Thérage <therage.kevin@gmail.com>
22+
*/
23+
class ContextualizedDumperTest extends TestCase
24+
{
25+
public function testContextualizedCliDumper()
26+
{
27+
$wrappedDumper = new CliDumper('php://output');
28+
$wrappedDumper->setColors(true);
29+
30+
$var = 'example';
31+
$href = sprintf('file://%s#L%s', __FILE__, 37);
32+
$dumper = new ContextualizedDumper($wrappedDumper, [new SourceContextProvider()]);
33+
$cloner = new VarCloner();
34+
$data = $cloner->cloneVar($var);
35+
36+
ob_start();
37+
$dumper->dump($data);
38+
$out = ob_get_clean();
39+
40+
$this->assertStringContainsString("\e]8;;{$href}\e\\\e[", $out);
41+
$this->assertStringContainsString("m{$var}\e[", $out);
42+
}
43+
}

src/Symfony/Component/VarDumper/VarDumper.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
1515
use Symfony\Component\VarDumper\Cloner\VarCloner;
1616
use Symfony\Component\VarDumper\Dumper\CliDumper;
17+
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
18+
use Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
1719
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
1820

1921
// Load the global dump() function
@@ -38,6 +40,8 @@ public static function dump($var)
3840
$dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper() : new HtmlDumper();
3941
}
4042

43+
$dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);
44+
4145
self::$handler = function ($var) use ($cloner, $dumper) {
4246
$dumper->dump($cloner->cloneVar($var));
4347
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy