diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index 6786cf6a11803..df61aefb6f2fc 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -127,6 +127,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is } $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; $frames[] = array('function' => ''); + $collapse = false; for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { $f = $frames[$i]; @@ -145,6 +146,13 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is $f = self::castFrameStub($frame, array(), $frame, true); if (isset($f[$prefix.'src'])) { foreach ($f[$prefix.'src']->value as $label => $frame) { + if (0 === strpos($label, "\0~collapse=0")) { + if ($collapse) { + $label = substr_replace($label, '1', 11, 1); + } else { + $collapse = true; + } + } $label = substr_replace($label, "title=Stack level $j.&", 2, 0); } $f = $frames[$i - 1]; @@ -162,7 +170,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is } else { $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; } - $a[$label] = $frame; + $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; $lastCall = $call; } @@ -197,9 +205,10 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $caller = isset($f['function']) ? sprintf('in %s() on line %d', (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'], $f['line']) : null; $src = $f['line']; $srcKey = $f['file']; - $ellipsis = (new LinkStub($srcKey, 0))->attr; - $ellipsisTail = isset($ellipsis['ellipsis-tail']) ? $ellipsis['ellipsis-tail'] : 0; - $ellipsis = isset($ellipsis['ellipsis']) ? $ellipsis['ellipsis'] : 0; + $ellipsis = new LinkStub($srcKey, 0); + $srcAttr = 'collapse='.(int) $ellipsis->inVendor; + $ellipsisTail = isset($ellipsis->attr['ellipsis-tail']) ? $ellipsis->attr['ellipsis-tail'] : 0; + $ellipsis = isset($ellipsis->attr['ellipsis']) ? $ellipsis->attr['ellipsis'] : 0; if (file_exists($f['file']) && 0 <= self::$srcContext) { if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { @@ -225,8 +234,11 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $ellipsis += 1 + strlen($f['line']); } } + $srcAttr .= '&separator= '; + } else { + $srcAttr .= '&separator=:'; } - $srcAttr = $ellipsis ? 'ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; + $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(array("\0~$srcAttr\0$srcKey" => $src)); } } @@ -329,7 +341,7 @@ private static function extractSource($srcLines, $line, $srcContext, $title, $la } } $c->attr['lang'] = $lang; - $srcLines[sprintf("\0~%d\0", $i + $line - $srcContext)] = $c; + $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; } return new EnumStub($srcLines); diff --git a/src/Symfony/Component/VarDumper/Caster/LinkStub.php b/src/Symfony/Component/VarDumper/Caster/LinkStub.php index eb9bc85c914f9..24f360b8f5553 100644 --- a/src/Symfony/Component/VarDumper/Caster/LinkStub.php +++ b/src/Symfony/Component/VarDumper/Caster/LinkStub.php @@ -18,6 +18,8 @@ */ class LinkStub extends ConstStub { + public $inVendor = false; + private static $vendorRoots; private static $composerRoots; @@ -50,10 +52,10 @@ public function __construct($label, $line = 0, $href = null) if ($label !== $this->attr['file'] = realpath($href) ?: $href) { return; } - if ($composerRoot = $this->getComposerRoot($href, $inVendor)) { + if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { $this->attr['ellipsis'] = strlen($href) - strlen($composerRoot) + 1; $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1 + ($inVendor ? 2 + strlen(implode(array_slice(explode(DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); + $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + strlen(implode(array_slice(explode(DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); } elseif (3 < count($ellipsis = explode(DIRECTORY_SEPARATOR, $href))) { $this->attr['ellipsis'] = 2 + strlen(implode(array_slice($ellipsis, -2))); $this->attr['ellipsis-type'] = 'path'; diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 8e86b054c05b0..4634fb915ea62 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -122,7 +122,7 @@ public static function castReflectionGenerator(\ReflectionGenerator $c, array $a $function = new FrameStub($frame, false, true); $function = ExceptionCaster::castFrameStub($function, array(), $function, true); $a[$prefix.'executing'] = new EnumStub(array( - $frame['class'].$frame['type'].$frame['function'].'()' => $function[$prefix.'src'], + "\0~separator= \0".$frame['class'].$frame['type'].$frame['function'].'()' => $function[$prefix.'src'], )); } diff --git a/src/Symfony/Component/VarDumper/Cloner/Cursor.php b/src/Symfony/Component/VarDumper/Cloner/Cursor.php index 9db55992e4aa9..888f4f2be33b9 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Cursor.php +++ b/src/Symfony/Component/VarDumper/Cloner/Cursor.php @@ -39,4 +39,5 @@ class Cursor public $hashCut = 0; public $stop = false; public $attr = array(); + public $skipChildren = false; } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 3de76cdc7da42..81e0477cbd215 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -355,10 +355,16 @@ private function dumpItem($dumper, $cursor, &$refs, $item) $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); if ($withChildren) { - $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + if ($cursor->skipChildren) { + $withChildren = false; + $cut = -1; + } else { + $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + } } elseif ($children && 0 <= $cut) { $cut += count($children); } + $cursor->skipChildren = false; $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); break; diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 086b2a2d6cd03..f1ea7fa01d755 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -51,6 +51,9 @@ class CliDumper extends AbstractDumper "\033" => '\e', ); + protected $collapseNextHash = false; + protected $expandNextHash = false; + /** * {@inheritdoc} */ @@ -253,6 +256,11 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild) { $this->dumpKey($cursor); + if ($this->collapseNextHash) { + $cursor->skipChildren = true; + $this->collapseNextHash = $hasChild = false; + } + $class = $this->utf8Encode($class); if (Cursor::HASH_OBJECT === $type) { $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{'; @@ -368,7 +376,15 @@ protected function dumpKey(Cursor $cursor) break; } - $this->line .= $bin.$this->style($style, $key[1], $attr).': '; + if (isset($attr['collapse'])) { + if ($attr['collapse']) { + $this->collapseNextHash = true; + } else { + $this->expandNextHash = true; + } + } + + $this->line .= $bin.$this->style($style, $key[1], $attr).(isset($attr['separator']) ? $attr['separator'] : ': '); } else { // This case should not happen $this->line .= '-'.$bin.'"'.$this->style('private', $key, array('class' => '')).'": '; @@ -397,6 +413,21 @@ protected function style($style, $value, $attr = array()) $this->colors = $this->supportsColors(); } + if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { + $prefix = substr($value, 0, -$attr['ellipsis']); + if ('cli' === PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && 0 === strpos($prefix, $_SERVER[$pwd])) { + $prefix = '.'.substr($prefix, strlen($_SERVER[$pwd])); + } + if (!empty($attr['ellipsis-tail'])) { + $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); + $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); + } else { + $value = substr($value, -$attr['ellipsis']); + } + + return $this->style('default', $prefix).$this->style($style, $value); + } + $style = $this->styles[$style]; $map = static::$controlCharsMap; diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index e57d04065b6be..54d97b175e648 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -366,7 +366,6 @@ function xpathString(str) { for (i = 0; i < len; ++i) { elt = t[i]; if ('SAMP' == elt.tagName) { - elt.className = 'sf-dump-expanded'; a = elt.previousSibling || {}; if ('A' != a.tagName) { a = doc.createElement('A'); @@ -383,7 +382,8 @@ function xpathString(str) { x += elt.parentNode.getAttribute('data-depth')/1; } elt.setAttribute('data-depth', x); - if (x > options.maxDepth) { + if (elt.className ? 'sf-dump-expanded' !== elt.className : (x > options.maxDepth)) { + elt.className = 'sf-dump-expanded'; toggle(a); } } else if ('sf-dump-ref' == elt.className && (a = elt.getAttribute('href'))) { @@ -728,15 +728,25 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild) { parent::enterHash($cursor, $type, $class, false); + if ($cursor->skipChildren) { + $cursor->skipChildren = false; + $eol = ' class=sf-dump-compact>'; + } elseif ($this->expandNextHash) { + $this->expandNextHash = false; + $eol = ' class=sf-dump-expanded>'; + } else { + $eol = '>'; + } + if ($hasChild) { + $this->line .= 'refIndex) { $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; - $this->line .= sprintf('', $this->dumpId, $r); - } else { - $this->line .= ''; + $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); } + $this->line .= $eol; $this->dumpLine($cursor->depth); } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 4e1e3682dc9f3..92cf6fb88299c 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -46,20 +46,13 @@ public function testDefaultSettings() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : $ref = array('foo'); - : $e = $this->getTestException('foo', $ref); - : - arguments: { - $msg: "foo" - &$ref: array:1 [ …1] - } + %s%eTests%eCaster%eExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:40 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testDefaultSettings() {} %A EODUMP; @@ -73,19 +66,13 @@ public function testSeek() $expectedDump = <<<'EODUMP' { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : { - : $e = $this->getTestException(2); - : - arguments: { - $msg: 2 - } + %s%eTests%eCaster%eExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:65 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testSeek() {} %A EODUMP; @@ -104,16 +91,13 @@ public function testNoArgs() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : { - : $e = $this->getTestException(1); - : ExceptionCaster::$traceArgs = false; + %sExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:84 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testNoArgs() {} %A EODUMP; @@ -132,8 +116,8 @@ public function testNoSrcContext() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php: 28 - %sExceptionCasterTest.php: %d + %s%eTests%eCaster%eExceptionCasterTest.php:28 + %s%eTests%eCaster%eExceptionCasterTest.php:%d %A EODUMP; @@ -161,7 +145,7 @@ public function testHtmlDump() #line: 28 trace: { %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php: 28 +Stack level %d.">%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:28 …%d } } @@ -197,10 +181,10 @@ public function testFrameWithTwig() 0 => { class: "__TwigTemplate_VarDumperFixture_u75a09" src: { - %sTwig.php:1: { - : - : foo bar - : twig source + %sTwig.php:1 { + › + › foo bar + › twig source } } } @@ -210,10 +194,10 @@ class: "__TwigTemplate_VarDumperFixture_u75a09" %A } src: { - %sExceptionCasterTest.php:2: { - : foo bar - : twig source - : + %sExceptionCasterTest.php:2 { + › foo bar + › twig source + › } } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index b7080b73eda80..71eecc1aa896d 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -174,11 +174,11 @@ public function testGenerator() Generator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} executing: { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): { - %sGeneratorDemo.php:14: { - : { - : yield from bar(); - : } + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() { + %sGeneratorDemo.php:14 { + › { + › yield from bar(); + › } } } } @@ -197,31 +197,23 @@ public function testGenerator() 0 => ReflectionGenerator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} trace: { - %sGeneratorDemo.php:9: { - : { - : yield 1; - : } - } - %sGeneratorDemo.php:20: { - : { - : yield from GeneratorDemo::foo(); - : } - } - %sGeneratorDemo.php:14: { - : { - : yield from bar(); - : } + %s%eTests%eFixtures%eGeneratorDemo.php:9 { + › { + › yield 1; + › } } + %s%eTests%eFixtures%eGeneratorDemo.php:20 { …} + %s%eTests%eFixtures%eGeneratorDemo.php:14 { …} } closed: false } 1 => Generator { executing: { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { - %sGeneratorDemo.php:10: { - : yield 1; - : } - : + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() { + %sGeneratorDemo.php:10 { + › yield 1; + › } + › } } } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index f9a208c6303bf..a496a8c09ff20 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -86,7 +86,7 @@ class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest" default: null } } - file: "{$var['file']}" + file: "%s%eTests%eFixtures%edumb-var.php" line: "{$var['line']} to {$var['line']}" } "line" => {$var['line']} @@ -361,30 +361,16 @@ public function testThrowingCaster() ⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r} #message: "Unexpected Exception thrown from a caster: Foobar" trace: { - %sTwig.php:2: { - : foo bar - : twig source - : + %sTwig.php:2 { + › foo bar + › twig source + › } - %sTemplate.php:%d: { - : try { - : \$this->doDisplay(\$context, \$blocks); - : } catch (Twig%sError \$e) { - } - %sTemplate.php:%d: { - : { - : \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks)); - : } - } - %sTemplate.php:%d: { - : try { - : \$this->display(\$context); - : } catch (%s \$e) { - } - %sCliDumperTest.php:%d: { -%A - } - } + %s%eTemplate.php:%d { …} + %s%eTemplate.php:%d { …} + %s%eTemplate.php:%d { …} + %s%eTests%eDumper%eCliDumperTest.php:%d { …} +%A } } %Awrapper_type: "PHP" stream_type: "MEMORY"