Skip to content

Commit

Permalink
Fix node being undetected as part of function signature when too deep…
Browse files Browse the repository at this point in the history
…ly nested. (#1847)

* Fix node being undetected as part of function signature when too deeply nested.

* Fix coding standards.

---------

Co-authored-by: Nicolas Giraud <nicolas.giraud@aareon.com>
  • Loading branch information
niconoe- and niconoe- committed Apr 25, 2023
1 parent 37dd2f5 commit 9bbe499
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/PhpParser/Visitor/ReflectionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,25 @@ public function leaveNode(Node $node): ?Node
return null;
}

/**
* Loop on all parents of the node until one is a Node\Param or a function-like, which means it is part of a
* signature.
*/
private function isPartOfFunctionSignature(Node $node): bool
{
if ($this->isFunctionLikeNode($node)) {
return true;
}

$parent = ParentConnector::findParent($node);

if ($parent === null) {
return false;
if ($node instanceof Node\Param) {
return true;
}

return $parent instanceof Node\Param || $node instanceof Node\Param;
do {
$node = ParentConnector::findParent($node);
} while ($node !== null && !$node instanceof Node\Param);

return $node !== null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace InfectionReflectionPartOfSignature;

class Test
{
public function foo(
int $param,
#[CustomAttribute(false)]
$test = 2.0
): bool {
return count([]) === 1;
}
}
33 changes: 33 additions & 0 deletions tests/phpunit/PhpParser/Visitor/ReflectionVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ public function test_it_marks_nodes_which_are_part_of_the_function_signature(str
$this->assertSame($expected, $spyVisitor->isPartOfSignature());
}

/**
* @dataProvider isPartOfSignatureFlagWithAttributesProvider
*/
public function test_it_marks_nodes_which_are_part_of_the_function_signature_with_attributes(string $nodeClass, bool $expected): void
{
$code = $this->getFileContent('Reflection/rv-part-of-signature-flag-with-attributes.php');

$spyVisitor = $this->getPartOfSignatureSpyVisitor($nodeClass);

$this->parseAndTraverse($code, $spyVisitor);

$this->assertSame($expected, $spyVisitor->isPartOfSignature());
}

public function test_it_detects_if_it_is_traversing_inside_class_method(): void
{
$code = $this->getFileContent('Reflection/rv-inside-class-method.php');
Expand Down Expand Up @@ -210,6 +224,25 @@ public function isPartOfSignatureFlagProvider(): iterable
yield [Node\Expr\Array_::class, false]; // []
}

public function isPartOfSignatureFlagWithAttributesProvider(): iterable
{
yield [Node\Stmt\ClassMethod::class, true];

yield [Node\Param::class, true]; // $param

yield [Node\Expr\ConstFetch::class, true]; // false

yield [Node\Scalar\DNumber::class, true]; // 2.0

yield [Node\Scalar\LNumber::class, false]; // 1

yield [Node\Expr\BinaryOp\Identical::class, false]; // ===

yield [Node\Arg::class, false];

yield [Node\Expr\Array_::class, false]; // []
}

private function getPartOfSignatureSpyVisitor(string $nodeClass)
{
return new class($nodeClass) extends NodeVisitorAbstract {
Expand Down

0 comments on commit 9bbe499

Please sign in to comment.