Skip to content

[VarDumper] Add support of named arguments to dd() and dump() to display a label #48432

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Symfony/Component/VarDumper/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ CHANGELOG
---

* Add caster for `WeakMap`
* Add support of named arguments to `dd()` and `dump()` to display the argument name

6.2
---
Expand Down
27 changes: 27 additions & 0 deletions src/Symfony/Component/VarDumper/Caster/ScalarStub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\VarDumper\Caster;

use Symfony\Component\VarDumper\Cloner\Stub;

/**
* Represents any arbitrary value.
*
* @author Alexandre Daubois <alex.daubois@gmail.com>
*/
class ScalarStub extends Stub
{
public function __construct(mixed $value)
{
$this->value = $value;
}
}
8 changes: 8 additions & 0 deletions src/Symfony/Component/VarDumper/Caster/StubCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,12 @@ public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNeste

return $a;
}

public static function castScalar(ScalarStub $scalarStub, array $a, Stub $stub)
{
$stub->type = Stub::TYPE_SCALAR;
$stub->attr['value'] = $scalarStub->value;

return $a;
}
}
1 change: 1 addition & 0 deletions src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ abstract class AbstractCloner implements ClonerInterface
'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'],
'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'],
'Symfony\Component\VarDumper\Caster\ScalarStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castScalar'],

'Fiber' => ['Symfony\Component\VarDumper\Caster\FiberCaster', 'castFiber'],

Expand Down
12 changes: 11 additions & 1 deletion src/Symfony/Component/VarDumper/Cloner/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ public function withContext(array $context): static
return $data;
}

public function getContext(): array
{
return $this->context;
}

/**
* Seeks to a specific key in nested data structures.
*/
Expand Down Expand Up @@ -262,11 +267,12 @@ public function dump(DumperInterface $dumper)
{
$refs = [0];
$cursor = new Cursor();
$label = $this->context['label'] ?? '';

if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) {
$cursor->attr['if_links'] = true;
$cursor->hashType = -1;
$dumper->dumpScalar($cursor, 'default', '^');
$dumper->dumpScalar($cursor, 'default', $label.'^');
$cursor->attr = ['if_links' => true];
$dumper->dumpScalar($cursor, 'default', ' ');
$cursor->hashType = 0;
Expand Down Expand Up @@ -362,6 +368,10 @@ private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs,
$dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);
break;

case Stub::TYPE_SCALAR:
$dumper->dumpScalar($cursor, 'default', $item->attr['value']);
break;

default:
throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type));
}
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/VarDumper/Cloner/Stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Stub
public const TYPE_ARRAY = 3;
public const TYPE_OBJECT = 4;
public const TYPE_RESOURCE = 5;
public const TYPE_SCALAR = 6;

public const STRING_BINARY = 1;
public const STRING_UTF8 = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(DataDumperInterface $wrappedDumper, array $contextPr

public function dump(Data $data)
{
$context = [];
$context = $data->getContext();
foreach ($this->contextProviders as $contextProvider) {
$context[$contextProvider::class] = $contextProvider->getContext();
}
Expand Down
33 changes: 24 additions & 9 deletions src/Symfony/Component/VarDumper/Resources/functions/dump.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,36 @@
* file that was distributed with this source code.
*/

use Symfony\Component\VarDumper\Caster\ScalarStub;
use Symfony\Component\VarDumper\VarDumper;

if (!function_exists('dump')) {
/**
* @author Nicolas Grekas <p@tchwork.com>
* @author Alexandre Daubois <alex.daubois@gmail.com>
*/
function dump(mixed $var, mixed ...$moreVars): mixed
function dump(mixed ...$vars): mixed
{
VarDumper::dump($var);
if (!$vars) {
VarDumper::dump(new ScalarStub('🐛'));

foreach ($moreVars as $v) {
VarDumper::dump($v);
return null;
}

if (1 < func_num_args()) {
return func_get_args();
if (isset($vars[0]) && 1 === count($vars)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

count($vars) is called twice, maybe use an intermediary var to avoid doing the job twice?

VarDumper::dump($vars[0]);
$k = 0;
} else {
foreach ($vars as $k => $v) {
VarDumper::dump($v, is_int($k) ? 1 + $k : $k);
}
}

return $var;
if (1 < count($vars)) {
return $vars;
}

return $vars[$k];
}
}

Expand All @@ -41,8 +52,12 @@ function dd(...$vars): void
header('HTTP/1.1 500 Internal Server Error');
}

foreach ($vars as $v) {
VarDumper::dump($v);
if (isset($vars[0]) && 1 === count($vars)) {
VarDumper::dump($vars[0]);
} else {
foreach ($vars as $k => $v) {
VarDumper::dump($v, is_int($k) ? 1 + $k : $k);
}
}

exit(1);
Expand Down
16 changes: 15 additions & 1 deletion src/Symfony/Component/VarDumper/Tests/Caster/StubCasterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Symfony\Component\VarDumper\Caster\ArgsStub;
use Symfony\Component\VarDumper\Caster\ClassStub;
use Symfony\Component\VarDumper\Caster\LinkStub;
use Symfony\Component\VarDumper\Caster\ScalarStub;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
Expand Down Expand Up @@ -87,6 +88,19 @@ public function testArgsStubWithClosure()
$this->assertDumpMatchesFormat($expectedDump, $args);
}

public function testEmptyStub()
{
$args = [new ScalarStub('🐛')];

$expectedDump = <<<'EODUMP'
array:1 [
0 => 🐛
]
EODUMP;

$this->assertDumpMatchesFormat($expectedDump, $args);
}

public function testLinkStub()
{
$var = [new LinkStub(__CLASS__, 0, __FILE__)];
Expand Down Expand Up @@ -203,7 +217,7 @@ public function testClassStubWithAnonymousClass()

$expectedDump = <<<'EODUMP'
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>
<span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:195" rel="noopener noreferrer"><span class=sf-dump-str title="19 characters">Exception@anonymous</span></a>"
<span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:209" rel="noopener noreferrer"><span class=sf-dump-str title="19 characters">Exception@anonymous</span></a>"
</samp>]
</bar>
EODUMP;
Expand Down
43 changes: 41 additions & 2 deletions src/Symfony/Component/VarDumper/Tests/Dumper/FunctionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@

class FunctionsTest extends TestCase
{
public function testDumpWithoutArg()
{
$this->setupVarDumper();

ob_start();
$return = dump();
ob_end_clean();

$this->assertNull($return);
}

public function testDumpReturnsFirstArg()
{
$this->setupVarDumper();
Expand All @@ -28,7 +39,20 @@ public function testDumpReturnsFirstArg()
$return = dump($var1);
ob_end_clean();

$this->assertEquals($var1, $return);
$this->assertSame($var1, $return);
}

public function testDumpReturnsFirstNamedArgWithoutSectionName()
{
$this->setupVarDumper();

$var1 = 'a';

ob_start();
$return = dump(first: $var1);
ob_end_clean();

$this->assertSame($var1, $return);
}

public function testDumpReturnsAllArgsInArray()
Expand All @@ -43,7 +67,22 @@ public function testDumpReturnsAllArgsInArray()
$return = dump($var1, $var2, $var3);
ob_end_clean();

$this->assertEquals([$var1, $var2, $var3], $return);
$this->assertSame([$var1, $var2, $var3], $return);
}

public function testDumpReturnsAllNamedArgsInArray()
{
$this->setupVarDumper();

$var1 = 'a';
$var2 = 'b';
$var3 = 'c';

ob_start();
$return = dump($var1, second: $var2, third: $var3);
ob_end_clean();

$this->assertSame([$var1, 'second' => $var2, 'third' => $var3], $return);
}

protected function setupVarDumper()
Expand Down
18 changes: 14 additions & 4 deletions src/Symfony/Component/VarDumper/VarDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ class VarDumper
*/
private static $handler;

public static function dump(mixed $var)
/**
* @param string|null $label
*/
public static function dump(mixed $var/* , string $label = null */)
{
$label = 2 <= \func_num_args() ? func_get_arg(1) : null;
if (null === self::$handler) {
self::register();
}

return (self::$handler)($var);
return (self::$handler)($var, $label);
}

public static function setHandler(callable $callable = null): ?callable
Expand Down Expand Up @@ -90,8 +94,14 @@ private static function register(): void
$dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);
}

self::$handler = function ($var) use ($cloner, $dumper) {
$dumper->dump($cloner->cloneVar($var));
self::$handler = function ($var, string $label = null) use ($cloner, $dumper) {
$var = $cloner->cloneVar($var);

if (null !== $label) {
$var = $var->withContext(['label' => $label]);
}

$dumper->dump($var);
};
}

Expand Down