feature #19714 [VarDumper] Handle "title" attribute on virtual properties (nicolas-grekas)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[VarDumper] Handle "title" attribute on virtual properties

| Q             | A
| ------------- | ---
| Branch?       | master
| New feature?  | yes
| Tests pass?   | yes
| License       | MIT

As seen with @wouterj , it would be better to *not* display the stack level in front of each stack line.
This PR does just that, and moves the stack level to a title attribute in HtmlDumper.

![capture du 2016-08-23 14-09-43](https://cloud.githubusercontent.com/assets/243674/17891395/cc40b088-693b-11e6-8523-89ff51be929a.png)

Commits
-------

19bcf63 [VarDumper] Handle "title" attribute on virtual properties
This commit is contained in:
Fabien Potencier 2016-08-23 10:20:39 -07:00
commit 865f344143
6 changed files with 70 additions and 30 deletions

View File

@ -89,6 +89,7 @@ class ExceptionCaster
$stub->handle = 0;
$frames = $trace->value;
$prefix = Caster::PREFIX_VIRTUAL;
$format = "\0~Stack level %s.\0%s";
$a = array();
$j = count($frames);
@ -124,7 +125,7 @@ class ExceptionCaster
$frame->value['args'] = $f[$prefix.'args'];
}
}
$a[$prefix.$j.'. '.$label] = $frame;
$a[sprintf($format, $j, $label)] = $frame;
$lastCall = ' ==> '.$call;
}

View File

@ -342,13 +342,16 @@ class CliDumper extends AbstractDumper
} elseif (0 < strpos($key, "\0", 1)) {
$key = explode("\0", substr($key, 1), 2);
switch ($key[0]) {
switch ($key[0][0]) {
case '+': // User inserted keys
$attr['dynamic'] = true;
$this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
break 2;
case '~':
$style = 'meta';
if (isset($key[0][1])) {
$attr['title'] = substr($key[0], 1);
}
break;
case '*':
$style = 'protected';

View File

@ -445,6 +445,8 @@ EOHTML
return sprintf('<abbr title="%s" class=sf-dump-%s>%s</abbr>', $v, $style, substr($v, $c + 1));
} elseif ('protected' === $style) {
$style .= ' title="Protected property"';
} elseif ('meta' === $style && isset($attr['title'])) {
$style .= sprintf(' title="%s"', htmlspecialchars($attr['title'], ENT_QUOTES, 'UTF-8'));
} elseif ('private' === $style) {
$style .= sprintf(' title="Private property defined in class:&#10;`%s`"', $attr['class']);
}

View File

@ -12,6 +12,8 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
use Symfony\Component\VarDumper\Caster\ExceptionCaster;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
class ExceptionCasterTest extends \PHPUnit_Framework_TestCase
@ -38,14 +40,14 @@ Exception {
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 23
#line: 25
-trace: {
%d. %sExceptionCasterTest.php:23: {
22: {
23: return new \Exception('foo');
24: }
%sExceptionCasterTest.php:25: {
24: {
25: return new \Exception('foo');
26: }
}
%d. %sExceptionCasterTest.php:%d: {
%sExceptionCasterTest.php:%d: {
%d: {
%d: $e = $this->getTestException(1);
%d:
@ -65,12 +67,12 @@ EODUMP;
$expectedDump = <<<'EODUMP'
{
%d. %sExceptionCasterTest.php:23: {
22: {
23: return new \Exception('foo');
24: }
%sExceptionCasterTest.php:25: {
24: {
25: return new \Exception('foo');
26: }
}
%d. %sExceptionCasterTest.php:%d: {
%sExceptionCasterTest.php:%d: {
%d: {
%d: $e = $this->getTestException(2);
%d:
@ -94,14 +96,14 @@ Exception {
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 23
#line: 25
-trace: {
%d. %sExceptionCasterTest.php:23: {
22: {
23: return new \Exception('foo');
24: }
%sExceptionCasterTest.php:25: {
24: {
25: return new \Exception('foo');
26: }
}
%d. %sExceptionCasterTest.php:%d: {
%sExceptionCasterTest.php:%d: {
%d: {
%d: $e = $this->getTestException(1);
%d: ExceptionCaster::$traceArgs = false;
@ -122,13 +124,45 @@ Exception {
#message: "foo"
#code: 0
#file: "%sExceptionCasterTest.php"
#line: 23
#line: 25
-trace: {
%d. %sExceptionCasterTest.php: 23
%d. %sExceptionCasterTest.php: %d
%sExceptionCasterTest.php: 25
%sExceptionCasterTest.php: %d
%A
EODUMP;
$this->assertDumpMatchesFormat($expectedDump, $e);
}
public function testHtmlDump()
{
$e = $this->getTestException(1);
ExceptionCaster::$srcContext = -1;
$h = fopen('php://memory', 'r+b');
$cloner = new VarCloner();
$cloner->setMaxItems(1);
$dumper = new HtmlDumper($h);
$dumper->setDumpHeader('<foo></foo>');
$dumper->setDumpBoundaries('<bar>', '</bar>');
$dumper->dump($cloner->cloneVar($e)->withRefHandles(false));
$dump = stream_get_contents($h, -1, 0);
fclose($h);
$expectedDump = <<<'EODUMP'
<foo></foo><bar><span class=sf-dump-note>Exception</span> {<samp>
#<span class=sf-dump-protected title="Protected property">message</span>: "<span class=sf-dump-str title="3 characters">foo</span>"
#<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span>
#<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%d characters">%sExceptionCasterTest.php</span>"
#<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>25</span>
-<span class=sf-dump-private title="Private property defined in class:&#10;`Exception`">trace</span>: {<samp>
<span class=sf-dump-meta title="Stack level %d.">%sExceptionCasterTest.php</span>: <span class=sf-dump-num>25</span>
&hellip;12
</samp>}
</samp>}
</bar>
EODUMP;
$this->assertStringMatchesFormat($expectedDump, $dump);
}
}

View File

@ -177,17 +177,17 @@ array:2 [
0 => ReflectionGenerator {
this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { }
trace: {
3. %sGeneratorDemo.php:9: {
%sGeneratorDemo.php:9: {
8: {
9: yield 1;
10: }
}
2. %sGeneratorDemo.php:20: {
%sGeneratorDemo.php:20: {
19: {
20: yield from GeneratorDemo::foo();
21: }
}
1. %sGeneratorDemo.php:14: {
%sGeneratorDemo.php:14: {
13: {
14: yield from bar();
15: }

View File

@ -288,23 +288,23 @@ stream resource {@{$ref}
: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
#message: "Unexpected Exception thrown from a caster: Foobar"
-trace: {
%d. {$twig}
%d. %sTemplate.php:%d: {
{$twig}
%sTemplate.php:%d: {
%d: try {
%d: \$this->doDisplay(\$context, \$blocks);
%d: } catch (Twig_Error \$e) {
}
%d. %sTemplate.php:%d: {
%sTemplate.php:%d: {
%d: {
%d: \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));
%d: }
}
%d. %sTemplate.php:%d: {
%sTemplate.php:%d: {
%d: try {
%d: \$this->display(\$context);
%d: } catch (Exception \$e) {
}
%d. %sCliDumperTest.php:{$line}: {
%sCliDumperTest.php:{$line}: {
%d: }
{$line}: };'),
%d: ));