Skip to content

Commit

Permalink
Update ProtectedVisibility/PublicVisibility to guard against missing …
Browse files Browse the repository at this point in the history
…reflection (infection#502)

* Update ProtectedVisibility/PublicVisibility to guard against missing reflection

It seems that PHP-Parser can't provide reflection for anonymous classes yet.

Fixes infection#501 for time being until nikic/PHP-Parser#543 gets fixed.

* PublicVisibility: test for presence of reflection in one place

* Update type hint to include null
  • Loading branch information
sanmai authored and raphaelstolt committed Nov 2, 2018
1 parent c3faa3f commit e53f86e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
7 changes: 6 additions & 1 deletion src/Mutator/FunctionSignature/ProtectedVisibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,14 @@ protected function mutatesNode(Node $node): bool

private function hasSameProtectedParentMethod(Node $node): bool
{
/** @var \ReflectionClass $reflection */
/** @var \ReflectionClass|null $reflection */
$reflection = $node->getAttribute(ReflectionVisitor::REFLECTION_CLASS_KEY);

if (!$reflection instanceof \ReflectionClass) {
// assuming the worst where a parent class has the same method
return true;
}

$parent = $reflection->getParentClass();

while ($parent) {
Expand Down
20 changes: 11 additions & 9 deletions src/Mutator/FunctionSignature/PublicVisibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,19 @@ private function isBlacklistedFunction(Node\Identifier $name): bool

private function hasSamePublicParentMethod(Node $node): bool
{
return $this->hasSamePublicMethodInInterface($node) || $this->hasSamePublicMethodInParentClass($node);
/** @var \ReflectionClass|null $reflection */
$reflection = $node->getAttribute(ReflectionVisitor::REFLECTION_CLASS_KEY);

if (!$reflection instanceof \ReflectionClass) {
// assuming the worst where an interface has the same method
return true;
}

return $this->hasSamePublicMethodInInterface($node, $reflection) || $this->hasSamePublicMethodInParentClass($node, $reflection);
}

private function hasSamePublicMethodInInterface(Node $node): bool
private function hasSamePublicMethodInInterface(Node $node, \ReflectionClass $reflection): bool
{
/** @var \ReflectionClass $reflection */
$reflection = $node->getAttribute(ReflectionVisitor::REFLECTION_CLASS_KEY);

foreach ($reflection->getInterfaces() as $reflectionInterface) {
try {
$method = $reflectionInterface->getMethod($node->name->name);
Expand All @@ -116,11 +121,8 @@ private function hasSamePublicMethodInInterface(Node $node): bool
return false;
}

private function hasSamePublicMethodInParentClass(Node $node): bool
private function hasSamePublicMethodInParentClass(Node $node, \ReflectionClass $reflection): bool
{
/** @var \ReflectionClass $reflection */
$reflection = $node->getAttribute(ReflectionVisitor::REFLECTION_CLASS_KEY);

$parent = $reflection->getParentClass();

while ($parent) {
Expand Down
16 changes: 16 additions & 0 deletions tests/Mutator/FunctionSignature/ProtectedVisibilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,22 @@ private function bar()
{
}
}
PHP
];

yield 'it does not mutate an anonymous class because reflection is not avalable' => [
<<<'PHP'
<?php
function something()
{
return new class() {
protected function anything()
{
return null;
}
};
}
PHP
];
}
Expand Down
16 changes: 16 additions & 0 deletions tests/Mutator/FunctionSignature/PublicVisibilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,22 @@ protected function bar()
{
}
}
PHP
];

yield 'it does not mutate an anonymous class because reflection is not avalable' => [
<<<'PHP'
<?php
function something()
{
return new class() {
public function anything()
{
return null;
}
};
}
PHP
];
}
Expand Down

0 comments on commit e53f86e

Please sign in to comment.