mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Merge pull request #250 from phpDocumentor/fix/modified-backtrace-arguments
Fix issue with modified backtrace
This commit is contained in:
@@ -15,4 +15,8 @@
|
|||||||
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix">
|
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix">
|
||||||
<exclude-pattern>*/src/*/Abstract*.php</exclude-pattern>
|
<exclude-pattern>*/src/*/Abstract*.php</exclude-pattern>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod">
|
||||||
|
<exclude-pattern>*/src/DocBlock/Tags/InvalidTag.php</exclude-pattern>
|
||||||
|
</rule>
|
||||||
</ruleset>
|
</ruleset>
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ use Closure;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
use ReflectionException;
|
||||||
use ReflectionFunction;
|
use ReflectionFunction;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function array_walk_recursive;
|
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function get_resource_type;
|
use function get_resource_type;
|
||||||
|
use function is_array;
|
||||||
use function is_object;
|
use function is_object;
|
||||||
use function is_resource;
|
use function is_resource;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
@@ -80,29 +81,12 @@ final class InvalidTag implements Tag
|
|||||||
$traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace');
|
$traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace');
|
||||||
$traceProperty->setAccessible(true);
|
$traceProperty->setAccessible(true);
|
||||||
|
|
||||||
$flatten =
|
|
||||||
/** @param mixed $value */
|
|
||||||
static function (&$value) : void {
|
|
||||||
if ($value instanceof Closure) {
|
|
||||||
$closureReflection = new ReflectionFunction($value);
|
|
||||||
$value = sprintf(
|
|
||||||
'(Closure at %s:%s)',
|
|
||||||
$closureReflection->getFileName(),
|
|
||||||
$closureReflection->getStartLine()
|
|
||||||
);
|
|
||||||
} elseif (is_object($value)) {
|
|
||||||
$value = sprintf('object(%s)', get_class($value));
|
|
||||||
} elseif (is_resource($value)) {
|
|
||||||
$value = sprintf('resource(%s)', get_resource_type($value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$trace = $exception->getTrace();
|
$trace = $exception->getTrace();
|
||||||
if (isset($trace[0]['args'])) {
|
if (isset($trace[0]['args'])) {
|
||||||
$trace = array_map(
|
$trace = array_map(
|
||||||
static function (array $call) use ($flatten) : array {
|
function (array $call) : array {
|
||||||
array_walk_recursive($call['args'], $flatten);
|
$call['args'] = array_map([$this, 'flattenArguments'], $call['args']);
|
||||||
|
|
||||||
return $call;
|
return $call;
|
||||||
},
|
},
|
||||||
@@ -117,6 +101,33 @@ final class InvalidTag implements Tag
|
|||||||
$traceProperty->setAccessible(false);
|
$traceProperty->setAccessible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws ReflectionException
|
||||||
|
*/
|
||||||
|
private function flattenArguments($value)
|
||||||
|
{
|
||||||
|
if ($value instanceof Closure) {
|
||||||
|
$closureReflection = new ReflectionFunction($value);
|
||||||
|
$value = sprintf(
|
||||||
|
'(Closure at %s:%s)',
|
||||||
|
$closureReflection->getFileName(),
|
||||||
|
$closureReflection->getStartLine()
|
||||||
|
);
|
||||||
|
} elseif (is_object($value)) {
|
||||||
|
$value = sprintf('object(%s)', get_class($value));
|
||||||
|
} elseif (is_resource($value)) {
|
||||||
|
$value = sprintf('resource(%s)', get_resource_type($value));
|
||||||
|
} elseif (is_array($value)) {
|
||||||
|
$value = array_map([$this, 'flattenArguments'], $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
public function render(?Formatter $formatter = null) : string
|
public function render(?Formatter $formatter = null) : string
|
||||||
{
|
{
|
||||||
if ($formatter === null) {
|
if ($formatter === null) {
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpDocumentor\Reflection;
|
||||||
|
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class ModifyBackTraceSafeTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testBackTraceModificationDoesNotImpactFunctionArguments()
|
||||||
|
{
|
||||||
|
$traverser = new Traverser();
|
||||||
|
$node1 = new Node();
|
||||||
|
$node1->children[] = new Node();
|
||||||
|
$node1->children[] = new Node();
|
||||||
|
|
||||||
|
$traverser->traverse([new Node(), $node1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
public $children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Traverser
|
||||||
|
{
|
||||||
|
public function traverse(array $nodes)
|
||||||
|
{
|
||||||
|
$this->traverseArray($nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function traverseArray(array $nodes): array
|
||||||
|
{
|
||||||
|
$doNodes = [];
|
||||||
|
|
||||||
|
foreach ($nodes as &$node) {
|
||||||
|
$node = $this->callback($node);
|
||||||
|
$node = $this->traverseNode($node);
|
||||||
|
|
||||||
|
$doNodes[] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $doNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callback(Node $class) : Node
|
||||||
|
{
|
||||||
|
$docblock = <<<DOCBLOCK
|
||||||
|
/**
|
||||||
|
* @see sql.php
|
||||||
|
*/
|
||||||
|
DOCBLOCK;
|
||||||
|
|
||||||
|
$factor = DocBlockFactory::createInstance();
|
||||||
|
|
||||||
|
$factor->create($docblock);
|
||||||
|
|
||||||
|
return $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function traverseNode(Node $node) : Node
|
||||||
|
{
|
||||||
|
if ($node->children) {
|
||||||
|
$this->traverseArray($node->children);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user