diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index 81bf186e5593..51c70dd5db9a 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -21,6 +21,7 @@ */ class ExceptionCaster { + public static $srcContext = 1; public static $traceArgs = true; public static $errorTypes = array( E_DEPRECATED => 'E_DEPRECATED', @@ -71,7 +72,7 @@ public static function castThrowingCasterException(ThrowingCasterException $e, a 'file' => $b[$prefix.'file'], 'line' => $b[$prefix.'line'], )); - $a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], 1, false, 0, -1 - count($a[$xPrefix.'trace']->value)); + $a[$xPrefix.'trace'] = new TraceStub($b[$xPrefix.'trace'], false, 0, -1 - count($a[$xPrefix.'trace']->value)); } unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); @@ -90,7 +91,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is $a = array(); $j = count($frames); - if (0 > $i = $trace->offset) { + if (0 > $i = $trace->sliceOffset) { $i = max(0, $j + $i); } if (!isset($trace->value[$i])) { @@ -98,7 +99,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'].'()' : ''; - for ($j -= $i++; isset($frames[$i]); ++$i, --$j) { + for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { $call = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[$i]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '???'; $a[Caster::PREFIX_VIRTUAL.$j.'. '.$call.$lastCall] = new FrameStub( @@ -108,7 +109,6 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is 'type' => isset($frames[$i]['type']) ? $frames[$i]['type'] : null, 'function' => isset($frames[$i]['function']) ? $frames[$i]['function'] : null, ) + $frames[$i - 1], - $trace->srcContext, $trace->keepArgs, true ); @@ -122,12 +122,11 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is 'type' => null, 'function' => '{main}', ) + $frames[$i - 1], - $trace->srcContext, $trace->keepArgs, true ); - if (null !== $trace->length) { - $a = array_slice($a, 0, $trace->length, true); + if (null !== $trace->sliceLength) { + $a = array_slice($a, 0, $trace->sliceLength, true); } return $a; @@ -146,8 +145,8 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $f['file'] = substr($f['file'], 0, -strlen($match[0])); $f['line'] = (int) $match[1]; } - if (file_exists($f['file']) && 0 <= $frame->srcContext) { - $src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], $frame->srcContext); + if (file_exists($f['file']) && 0 <= self::$srcContext) { + $src[$f['file'].':'.$f['line']] = self::extractSource(explode("\n", file_get_contents($f['file'])), $f['line'], self::$srcContext); if (!empty($f['class']) && is_subclass_of($f['class'], 'Twig_Template') && method_exists($f['class'], 'getDebugInfo')) { $template = isset($f['object']) ? $f['object'] : new $f['class'](new \Twig_Environment(new \Twig_Loader_Filesystem())); @@ -157,7 +156,7 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $templateSrc = explode("\n", method_exists($template, 'getSource') ? $template->getSource() : $template->getEnvironment()->getLoader()->getSource($templateName)); $templateInfo = $template->getDebugInfo(); if (isset($templateInfo[$f['line']])) { - $src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], $frame->srcContext); + $src[$templateName.':'.$templateInfo[$f['line']]] = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext); } } catch (\Twig_Error_Loader $e) { } @@ -247,15 +246,29 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte private static function extractSource(array $srcArray, $line, $srcContext) { - $src = ''; + $src = array(); for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { - $src .= (isset($srcArray[$i]) ? $srcArray[$i] : '')."\n"; + $src[] = (isset($srcArray[$i]) ? $srcArray[$i] : '')."\n"; } - if (!$srcContext) { - $src = trim($src); + + $ltrim = 0; + while (' ' === $src[0][$ltrim] || "\t" === $src[0][$ltrim]) { + $i = $srcContext << 1; + while ($i > 0 && $src[0][$ltrim] === $src[$i][$ltrim]) { + --$i; + } + if ($i) { + break; + } + ++$ltrim; + } + if ($ltrim) { + foreach ($src as $i => $line) { + $src[$i] = substr($line, $ltrim); + } } - return $src; + return implode('', $src); } } diff --git a/src/Symfony/Component/VarDumper/Caster/FrameStub.php b/src/Symfony/Component/VarDumper/Caster/FrameStub.php index 58686f9dbe13..1e1194dc85b8 100644 --- a/src/Symfony/Component/VarDumper/Caster/FrameStub.php +++ b/src/Symfony/Component/VarDumper/Caster/FrameStub.php @@ -18,14 +18,12 @@ */ class FrameStub extends EnumStub { - public $srcContext; public $keepArgs; public $inTraceStub; - public function __construct(array $trace, $srcContext = 1, $keepArgs = true, $inTraceStub = false) + public function __construct(array $frame, $keepArgs = true, $inTraceStub = false) { - $this->value = $trace; - $this->srcContext = $srcContext; + $this->value = $frame; $this->keepArgs = $keepArgs; $this->inTraceStub = $inTraceStub; } diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 1d83c335445c..3352c87b7f1f 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -74,6 +74,59 @@ public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested) return $a; } + public static function castGenerator(\Generator $c, array $a, Stub $stub, $isNested) + { + return class_exists('ReflectionGenerator', false) ? self::castReflectionGenerator(new \ReflectionGenerator($c), $a, $stub, $isNested) : $a; + } + + public static function castType(\ReflectionType $c, array $a, Stub $stub, $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += array( + $prefix.'type' => $c->__toString(), + $prefix.'allowsNull' => $c->allowsNull(), + $prefix.'isBuiltin' => $c->isBuiltin(), + ); + + return $a; + } + + public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($c->getThis()) { + $a[$prefix.'this'] = new CutStub($c->getThis()); + } + $x = $c->getFunction(); + $frame = array( + 'class' => isset($x->class) ? $x->class : null, + 'type' => isset($x->class) ? ($x->isStatic() ? '::' : '->') : null, + 'function' => $x->name, + 'file' => $c->getExecutingFile(), + 'line' => $c->getExecutingLine(), + ); + if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) { + $x = new \ReflectionGenerator($c->getExecutingGenerator()); + array_unshift($trace, array( + 'function' => 'yield', + 'file' => $x->getExecutingFile(), + 'line' => $x->getExecutingLine() - 1, + )); + $trace[] = $frame; + $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); + } else { + $x = new FrameStub($frame, false, true); + $x = ExceptionCaster::castFrameStub($x, array(), $x, true); + $a[$prefix.'executing'] = new EnumStub(array( + $frame['class'].$frame['type'].$frame['function'].'()' => $x[$prefix.'src'], + )); + } + + return $a; + } + public static function castClass(\ReflectionClass $c, array $a, Stub $stub, $isNested, $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; diff --git a/src/Symfony/Component/VarDumper/Caster/StubCaster.php b/src/Symfony/Component/VarDumper/Caster/StubCaster.php index 0b90358726a3..ebad5ba9844e 100644 --- a/src/Symfony/Component/VarDumper/Caster/StubCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/StubCaster.php @@ -54,6 +54,7 @@ public static function castEnum(EnumStub $c, array $a, Stub $stub, $isNested) if ($isNested) { $stub->class = ''; $stub->handle = 0; + $stub->value = null; $a = array(); diff --git a/src/Symfony/Component/VarDumper/Caster/TraceStub.php b/src/Symfony/Component/VarDumper/Caster/TraceStub.php index 98d6d892b932..59548acaee61 100644 --- a/src/Symfony/Component/VarDumper/Caster/TraceStub.php +++ b/src/Symfony/Component/VarDumper/Caster/TraceStub.php @@ -20,17 +20,17 @@ */ class TraceStub extends Stub { - public $srcContext; public $keepArgs; - public $offset; - public $length; + public $sliceOffset; + public $sliceLength; + public $numberingOffset; - public function __construct(array $trace, $srcContext = 1, $keepArgs = true, $offset = 0, $length = null) + public function __construct(array $trace, $keepArgs = true, $sliceOffset = 0, $sliceLength = null, $numberingOffset = 0) { $this->value = $trace; - $this->srcContext = $srcContext; $this->keepArgs = $keepArgs; - $this->offset = $offset; - $this->length = $length; + $this->sliceOffset = $sliceOffset; + $this->sliceLength = $sliceLength; + $this->numberingOffset = $numberingOffset; } } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 08bf7d33b374..afb7094a32b6 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -28,6 +28,9 @@ abstract class AbstractCloner implements ClonerInterface 'Symfony\Component\VarDumper\Caster\EnumStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castEnum', 'Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure', + 'Generator' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castGenerator', + 'ReflectionType' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castType', + 'ReflectionGenerator' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflectionGenerator', 'ReflectionClass' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClass', 'ReflectionFunctionAbstract' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castFunctionAbstract', 'ReflectionMethod' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castMethod', diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 51309c662b50..139f59eae643 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -149,7 +149,7 @@ protected function doClone($var) $stub->handle = $h; $a = $this->castObject($stub, 0 < $i); if ($v !== $stub->value) { - if (Stub::TYPE_OBJECT !== $stub->type) { + if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { break; } if ($useExt) { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index e304e15e05b2..dcbbb1789883 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use Symfony\Component\VarDumper\Test\VarDumperTestCase; +use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo; /** * @author Nicolas Grekas @@ -72,7 +73,7 @@ public function testClosureCaster() \$b: & 123 } file: "%sReflectionCasterTest.php" - line: "62 to 62" + line: "63 to 63" } EOTXT , $var @@ -92,11 +93,92 @@ public function testReturnType() returnType: "int" class: "Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest" this: Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest { …} - file: "%sReflectionCasterTest.php(87) : eval()'d code" + file: "%sReflectionCasterTest.php(88) : eval()'d code" line: "1 to 1" } EOTXT , $f ); } + + /** + * @requires PHP 7.0 + */ + public function testGenerator() + { + $g = new GeneratorDemo(); + $g = $g->baz(); + $r = new \ReflectionGenerator($g); + + $xDump = <<<'EODUMP' +Generator { + this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} + executing: { + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): { + %sGeneratorDemo.php:14: """ + {\n + yield from bar();\n + }\n + """ + } + } +} +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $g); + + foreach ($g as $v) { + break; + } + + $xDump = <<<'EODUMP' +array:2 [ + 0 => ReflectionGenerator { + this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} + trace: { + 3. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() ==> yield(): { + src: { + %sGeneratorDemo.php:9: """ + {\n + yield 1;\n + }\n + """ + } + } + 2. Symfony\Component\VarDumper\Tests\Fixtures\bar() ==> Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { + src: { + %sGeneratorDemo.php:20: """ + {\n + yield from GeneratorDemo::foo();\n + }\n + """ + } + } + 1. Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() ==> Symfony\Component\VarDumper\Tests\Fixtures\bar(): { + src: { + %sGeneratorDemo.php:14: """ + {\n + yield from bar();\n + }\n + """ + } + } + } + } + 1 => Generator { + executing: { + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { + %sGeneratorDemo.php:10: """ + yield 1;\n + }\n + \n + """ + } + } + } +] +EODUMP; + + $this->assertDumpMatchesFormat($xDump, array($r, $r->getExecutingGenerator())); + } } diff --git a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php index 66144165bb8b..9cb606fadcb7 100644 --- a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php @@ -232,45 +232,45 @@ public function testThrowingCaster() %d. __TwigTemplate_VarDumperFixture_u75a09->doDisplay() ==> new Exception(): { src: { %sTwig.php:19: """ - // line 2\\n - throw new \Exception('Foobar');\\n - }\\n + // line 2\\n + throw new \Exception('Foobar');\\n + }\\n """ {$twig} } } %d. Twig_Template->displayWithErrorHandling() ==> __TwigTemplate_VarDumperFixture_u75a09->doDisplay(): { src: { %sTemplate.php:%d: """ - try {\\n - \$this->doDisplay(\$context, \$blocks);\\n - } catch (Twig_Error \$e) {\\n + try {\\n + \$this->doDisplay(\$context, \$blocks);\\n + } catch (Twig_Error \$e) {\\n """ } } %d. Twig_Template->display() ==> Twig_Template->displayWithErrorHandling(): { src: { %sTemplate.php:%d: """ - {\\n - \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));\\n - }\\n + {\\n + \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks));\\n + }\\n """ } } %d. Twig_Template->render() ==> Twig_Template->display(): { src: { %sTemplate.php:%d: """ - try {\\n - \$this->display(\$context);\\n - } catch (Exception \$e) {\\n + try {\\n + \$this->display(\$context);\\n + } catch (Exception \$e) {\\n """ } } %d. %slosure%s() ==> Twig_Template->render(): { src: { %sCliDumperTest.php:{$line}: """ - }\\n - };'),\\n - ));\\n + }\\n + };'),\\n + ));\\n """ } } diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/GeneratorDemo.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/GeneratorDemo.php new file mode 100644 index 000000000000..e2d24c8c0eac --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/GeneratorDemo.php @@ -0,0 +1,21 @@ + 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