/** * @param \Generator $generator * @param string $prefix */ public function __construct(\Generator $generator, string $prefix) { $yielded = $generator->current(); $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), $generator->key()); if (!$generator->valid()) { parent::__construct($prefix); return; } $reflGen = new \ReflectionGenerator($generator); $exeGen = $reflGen->getExecutingGenerator(); if ($isSubgenerator = $exeGen !== $generator) { $reflGen = new \ReflectionGenerator($exeGen); } parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile())); }
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; }
/** * @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())); }
/** * @requires PHP 7.0 */ public function testGenerator() { if (extension_loaded('xdebug')) { $this->markTestSkipped('xdebug is active'); } $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: { : { : yield from bar(); : } } } } } EODUMP; $this->assertDumpMatchesFormat($xDump, $g); foreach ($g as $v) { break; } $xDump = <<<'EODUMP' array:2 [ 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(); : } } } } 1 => Generator { executing: { Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { %sGeneratorDemo.php:10: { : yield 1; : } : } } } } ] EODUMP; $this->assertDumpMatchesFormat($xDump, array($r, $r->getExecutingGenerator())); }
/** * @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: { 13: { 14: yield from bar(); 15: } } } } } EODUMP; $this->assertDumpMatchesFormat($xDump, $g); foreach ($g as $v) { break; } $xDump = <<<'EODUMP' array:2 [ 0 => ReflectionGenerator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} trace: { %sGeneratorDemo.php:9: { 8: { 9: yield 1; 10: } } %sGeneratorDemo.php:20: { 19: { 20: yield from GeneratorDemo::foo(); 21: } } %sGeneratorDemo.php:14: { 13: { 14: yield from bar(); 15: } } } } 1 => Generator { executing: { Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { %sGeneratorDemo.php:10: { 9: yield 1; 10: } 11: } } } } ] EODUMP; $this->assertDumpMatchesFormat($xDump, array($r, $r->getExecutingGenerator())); }
/** * A general purpose function for creating error messages from generator yields * * @param \Generator $generator * @param string $prefix * @return string */ function makeGeneratorError(\Generator $generator, $prefix = "Generator error") { if (PHP_MAJOR_VERSION < 7 || !$generator->valid()) { return $prefix; } $reflGen = new \ReflectionGenerator($generator); $exeGen = $reflGen->getExecutingGenerator(); if ($isSubgenerator = $exeGen !== $generator) { $reflGen = new \ReflectionGenerator($exeGen); } return sprintf("{$prefix} on line %s in %s", $reflGen->getExecutingLine(), $reflGen->getExecutingFile()); }