Skip to content

Commit

Permalink
Parser: Refactor noRecurseCall
Browse files Browse the repository at this point in the history
  • Loading branch information
jnvsor committed Dec 28, 2024
1 parent 9fa1184 commit b65499b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 43 deletions.
Binary file modified build/kint.phar
Binary file not shown.
97 changes: 58 additions & 39 deletions src/Parser/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Parser
protected array $array_ref_stack = [];
protected array $object_hashes = [];
protected array $plugins = [];
protected bool $in_parse = false;

/**
* @param int $depth_limit Maximum depth to parse data
Expand All @@ -105,7 +106,7 @@ public function __construct(int $depth_limit = 0, ?string $caller = null)
*/
public function setCallerClass(?string $caller = null): void
{
$this->noRecurseCall();
$this->noCallInParse();

$this->caller_class = $caller;
}
Expand All @@ -123,7 +124,7 @@ public function getCallerClass(): ?string
*/
public function setDepthLimit(int $depth_limit = 0): void
{
$this->noRecurseCall();
$this->noCallInParse();

$this->depth_limit = $depth_limit;
}
Expand All @@ -140,39 +141,49 @@ public function getDepthLimit(): int
*/
public function parse(&$var, ContextInterface $c): AbstractValue
{
$type = \strtolower(\gettype($var));
$in_parse_stash = $this->in_parse;

if ($v = $this->applyPluginsBegin($var, $c, $type)) {
return $v;
}
try {
$this->in_parse = true;

$type = \strtolower(\gettype($var));

if ($v = $this->applyPluginsBegin($var, $c, $type)) {
return $v;
}

switch ($type) {
case 'array':
return $this->parseArray($var, $c);
case 'boolean':
case 'double':
case 'integer':
case 'null':
return $this->parseFixedWidth($var, $c);
case 'object':
return $this->parseObject($var, $c);
case 'resource':
return $this->parseResource($var, $c);
case 'string':
return $this->parseString($var, $c);
case 'resource (closed)':
return $this->parseResourceClosed($var, $c);

case 'unknown type': // @codeCoverageIgnore
default:
// These should never happen. Unknown is resource (closed) from old
// PHP versions and there shouldn't be any other types.
return $this->parseUnknown($var, $c); // @codeCoverageIgnore
switch ($type) {
case 'array':
return $this->parseArray($var, $c);
case 'boolean':
case 'double':
case 'integer':
case 'null':
return $this->parseFixedWidth($var, $c);
case 'object':
return $this->parseObject($var, $c);
case 'resource':
return $this->parseResource($var, $c);
case 'string':
return $this->parseString($var, $c);
case 'resource (closed)':
return $this->parseResourceClosed($var, $c);

case 'unknown type': // @codeCoverageIgnore
default:
// These should never happen. Unknown is resource (closed) from old
// PHP versions and there shouldn't be any other types.
return $this->parseUnknown($var, $c); // @codeCoverageIgnore
}
} finally {
$this->in_parse = $in_parse_stash;
}
}

public function addPlugin(PluginInterface $p): void
{
$this->noCallInParse();

if (!$types = $p->getTypes()) {
return;
}
Expand Down Expand Up @@ -209,25 +220,33 @@ public function addPlugin(PluginInterface $p): void

public function clearPlugins(): void
{
$this->noCallInParse();

$this->plugins = [];
}

/**
* @psalm-api
*
* @codeCoverageIgnore
*
* @deprecated Use noCallInParse
*/
protected function noRecurseCall(): void
{
$bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
\trigger_error('Kint\\Parser::noRecurseCall is deprecated and will be removed in Kint 7. Use noCallInParse instead.', E_USER_DEPRECATED);

$caller_frame = [
'function' => __FUNCTION__,
];
$this->noCallInParse();
}

while (isset($bt[0]['object']) && $bt[0]['object'] === $this) {
$caller_frame = \array_shift($bt);
}
final protected function noCallInParse(): void
{
if ($this->in_parse) {
$bt = \debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
$caller_frame = \reset($bt);

foreach ($bt as $frame) {
if (isset($frame['object']) && $frame['object'] === $this) {
throw new DomainException(__CLASS__.'::'.$caller_frame['function'].' cannot be called from inside a parse');
}
/** @psalm-var class-string $caller_frame['class'] */
throw new DomainException($caller_frame['class'].'::'.$caller_frame['function'].' cannot be called from inside a parse');
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/Parser/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ public function testSetDepthLimit()
}

/**
* @covers \Kint\Parser\Parser::noRecurseCall
* @covers \Kint\Parser\Parser::noCallInParse
*/
public function testNoRecurseCall()
public function testNoCallInParse()
{
$p = new Parser();
$p->setDepthLimit(42);
Expand All @@ -150,9 +150,9 @@ function (&$var, $v) use ($p2) {
}

/**
* @covers \Kint\Parser\Parser::noRecurseCall
* @covers \Kint\Parser\Parser::noCallInParse
*/
public function testNoRecurseCallWithRecursion()
public function testNoCallInParseWithRecursion()
{
$p = new Parser();
$p->setDepthLimit(42);
Expand Down

0 comments on commit b65499b

Please sign in to comment.