Skip to content

Commit a978c75

Browse files
[VarDumper] Add support for virtual properties
1 parent a8098b2 commit a978c75

File tree

9 files changed

+139
-7
lines changed

9 files changed

+139
-7
lines changed

src/Symfony/Component/VarDumper/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Add support for `FORCE_COLOR` environment variable
8+
* Add support for virtual properties
89

910
7.1
1011
---

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ private static function getClassProperties(\ReflectionClass $class): array
190190
$p->isPublic() => $p->name,
191191
$p->isProtected() => self::PREFIX_PROTECTED.$p->name,
192192
default => "\0".$className."\0".$p->name,
193-
}] = new UninitializedStub($p);
193+
}] = \PHP_VERSION_ID >= 80400 && $p->isVirtual() ? new VirtualStub($p) : new UninitializedStub($p);
194194
}
195195

196196
return $classProperties;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Caster;
13+
14+
class VirtualStub extends ConstStub
15+
{
16+
public function __construct(\ReflectionProperty $property)
17+
{
18+
parent::__construct('~'.($property->hasType() ? ' '.$property->getType() : ''), 'Virtual property');
19+
$this->attr['virtual'] = true;
20+
}
21+
}

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ class CliDumper extends AbstractDumper
3333
'default' => '0;38;5;208',
3434
'num' => '1;38;5;38',
3535
'const' => '1;38;5;208',
36+
'virtual' => '3',
3637
'str' => '1;38;5;113',
3738
'note' => '38;5;38',
3839
'ref' => '38;5;247',
39-
'public' => '',
40-
'protected' => '',
41-
'private' => '',
40+
'public' => '39',
41+
'protected' => '39',
42+
'private' => '39',
4243
'meta' => '38;5;170',
4344
'key' => '38;5;113',
4445
'index' => '38;5;38',
@@ -347,7 +348,10 @@ protected function dumpKey(Cursor $cursor): void
347348
if ($cursor->hashKeyIsBinary) {
348349
$key = $this->utf8Encode($key);
349350
}
350-
$attr = ['binary' => $cursor->hashKeyIsBinary];
351+
$attr = [
352+
'binary' => $cursor->hashKeyIsBinary,
353+
'virtual' => $cursor->attr['virtual'] ?? false,
354+
];
351355
$bin = $cursor->hashKeyIsBinary ? 'b' : '';
352356
$style = 'key';
353357
switch ($cursor->hashType) {
@@ -371,7 +375,7 @@ protected function dumpKey(Cursor $cursor): void
371375
// no break
372376
case Cursor::HASH_OBJECT:
373377
if (!isset($key[0]) || "\0" !== $key[0]) {
374-
$this->line .= '+'.$bin.$this->style('public', $key).': ';
378+
$this->line .= '+'.$bin.$this->style('public', $key, $attr).': ';
375379
} elseif (0 < strpos($key, "\0", 1)) {
376380
$key = explode("\0", substr($key, 1), 2);
377381

@@ -506,6 +510,9 @@ protected function style(string $style, string $value, array $attr = []): string
506510
if ('label' === $style && '' !== $value) {
507511
$value .= ' ';
508512
}
513+
if ($this->colors && ($attr['virtual'] ?? false)) {
514+
$value = "\033[{$this->styles['virtual']}m".$value;
515+
}
509516

510517
return $value;
511518
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class HtmlDumper extends CliDumper
2929
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',
3030
'num' => 'font-weight:bold; color:#1299DA',
3131
'const' => 'font-weight:bold',
32+
'virtual' => 'font-style:italic',
3233
'str' => 'font-weight:bold; color:#56DB3A',
3334
'note' => 'color:#1299DA',
3435
'ref' => 'color:#A0A0A0',
@@ -45,6 +46,7 @@ class HtmlDumper extends CliDumper
4546
'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',
4647
'num' => 'font-weight:bold; color:#1299DA',
4748
'const' => 'font-weight:bold',
49+
'virtual' => 'font-style:italic',
4850
'str' => 'font-weight:bold; color:#629755;',
4951
'note' => 'color:#6897BB',
5052
'ref' => 'color:#6E6E6E',
@@ -921,6 +923,9 @@ protected function style(string $style, string $value, array $attr = []): string
921923
if ('label' === $style) {
922924
$v .= ' ';
923925
}
926+
if ($attr['virtual'] ?? false) {
927+
$v = '<span class=sf-dump-virtual>'.$v.'</span>';
928+
}
924929

925930
return $v;
926931
}

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

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
use Symfony\Component\VarDumper\Caster\ClassStub;
1717
use Symfony\Component\VarDumper\Caster\LinkStub;
1818
use Symfony\Component\VarDumper\Caster\ScalarStub;
19+
use Symfony\Component\VarDumper\Caster\VirtualStub;
1920
use Symfony\Component\VarDumper\Cloner\VarCloner;
2021
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
2122
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
2223
use Symfony\Component\VarDumper\Tests\Fixtures\FooInterface;
24+
use Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty;
2325

2426
class StubCasterTest extends TestCase
2527
{
@@ -101,6 +103,40 @@ public function testEmptyStub()
101103
$this->assertDumpMatchesFormat($expectedDump, $args);
102104
}
103105

106+
/**
107+
* @requires PHP 8.4
108+
*/
109+
public function testVirtualPropertyStub()
110+
{
111+
$class = new \ReflectionClass(VirtualProperty::class);
112+
$args = [new VirtualStub($class->getProperty('fullName'))];
113+
114+
$expectedDump = <<<'EODUMP'
115+
array:1 [
116+
0 => ~ string
117+
]
118+
EODUMP;
119+
120+
$this->assertDumpMatchesFormat($expectedDump, $args);
121+
}
122+
123+
/**
124+
* @requires PHP 8.4
125+
*/
126+
public function testVirtualPropertyWithoutTypeStub()
127+
{
128+
$class = new \ReflectionClass(VirtualProperty::class);
129+
$args = [new VirtualStub($class->getProperty('noType'))];
130+
131+
$expectedDump = <<<'EODUMP'
132+
array:1 [
133+
0 => ~
134+
]
135+
EODUMP;
136+
137+
$this->assertDumpMatchesFormat($expectedDump, $args);
138+
}
139+
104140
public function testLinkStub()
105141
{
106142
$var = [new LinkStub(__CLASS__, 0, __FILE__)];
@@ -217,7 +253,7 @@ public function testClassStubWithAnonymousClass()
217253

218254
$expectedDump = <<<'EODUMP'
219255
<foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded>
220-
<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>"
256+
<span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:245" rel="noopener noreferrer"><span class=sf-dump-str title="19 characters">Exception@anonymous</span></a>"
221257
</samp>]
222258
</bar>
223259
EODUMP;

src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\VarDumper\Dumper\AbstractDumper;
2222
use Symfony\Component\VarDumper\Dumper\CliDumper;
2323
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
24+
use Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty;
2425
use Twig\Environment;
2526
use Twig\Loader\FilesystemLoader;
2627

@@ -304,6 +305,21 @@ public function testFlags()
304305
putenv('DUMP_STRING_LENGTH=');
305306
}
306307

308+
/**
309+
* @requires PHP 8.4
310+
*/
311+
public function testVirtualProperties()
312+
{
313+
$this->assertDumpEquals(<<<EODUMP
314+
Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty {
315+
+firstName: "John"
316+
+lastName: "Doe"
317+
+fullName: ~ string
318+
-noType: ~
319+
}
320+
EODUMP, new VirtualProperty());
321+
}
322+
307323
public function testThrowingCaster()
308324
{
309325
$out = fopen('php://memory', 'r+');

src/Symfony/Component/VarDumper/Tests/Dumper/HtmlDumperTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\VarDumper\Caster\ImgStub;
1616
use Symfony\Component\VarDumper\Cloner\VarCloner;
1717
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
18+
use Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty;
1819

1920
/**
2021
* @author Nicolas Grekas <[email protected]>
@@ -117,6 +118,30 @@ public function testGet()
117118
);
118119
}
119120

121+
/**
122+
* @requires PHP 8.4
123+
*/
124+
public function testVirtualProperties()
125+
{
126+
$dumper = new HtmlDumper('php://output');
127+
$dumper->setDumpHeader('<foo></foo>');
128+
$dumper->setDumpBoundaries('<bar>', '</bar>');
129+
$cloner = new VarCloner();
130+
131+
$data = $cloner->cloneVar(new VirtualProperty());
132+
$out = $dumper->dump($data, true);
133+
134+
$this->assertStringMatchesFormat(<<<EODUMP
135+
<foo></foo><bar><span class=sf-dump-note>Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty</span> {<a class=sf-dump-ref>#%i</a><samp data-depth=1 class=sf-dump-expanded>
136+
+<span class=sf-dump-public title="Public property">firstName</span>: "<span class=sf-dump-str title="4 characters">John</span>"
137+
+<span class=sf-dump-public title="Public property">lastName</span>: "<span class=sf-dump-str title="3 characters">Doe</span>"
138+
+<span class=sf-dump-virtual><span class=sf-dump-public title="Public property">fullName</span></span>: <span class=sf-dump-virtual><span class=sf-dump-const title="Virtual property">~ string</span></span>
139+
-<span class=sf-dump-virtual><span class=sf-dump-private title="Private property defined in class:&#10;`Symfony\Component\VarDumper\Tests\Fixtures\VirtualProperty`">noType</span></span>: <span class=sf-dump-virtual><span class=sf-dump-const title="Virtual property">~</span></span>
140+
</samp>}
141+
</bar>
142+
EODUMP, $out);
143+
}
144+
120145
public function testCharset()
121146
{
122147
$var = mb_convert_encoding('Словарь', 'CP1251', 'UTF-8');
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Symfony\Component\VarDumper\Tests\Fixtures;
4+
5+
class VirtualProperty
6+
{
7+
public string $firstName = 'John';
8+
public string $lastName = 'Doe';
9+
10+
public string $fullName {
11+
get {
12+
return $this->firstName.' '.$this->lastName;
13+
}
14+
}
15+
16+
private $noType {
17+
get {
18+
return null;
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)