Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Rules/Methods/ConsistentConstructorRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function processNode(Node $node, Scope $scope): array

return array_merge(
$this->methodParameterComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, true),
$this->methodVisibilityComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method),
$this->methodVisibilityComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, $node->getOriginalNode()->name),
);
}

Expand Down
5 changes: 4 additions & 1 deletion src/Rules/Methods/MethodVisibilityComparisonHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Rules\Methods;

use PhpParser\Node;
use PHPStan\DependencyInjection\AutowiredService;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
Expand All @@ -15,7 +16,7 @@ final class MethodVisibilityComparisonHelper
{

/** @return list<IdentifierRuleError> */
public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method): array
public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, Node $node): array
{
/** @var list<IdentifierRuleError> $messages */
$messages = [];
Expand All @@ -32,6 +33,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr
))
->nonIgnorable()
->identifier('method.visibility')
->line($node->getStartLine())
->build();
}
} elseif ($method->isPrivate()) {
Expand All @@ -44,6 +46,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr
))
->nonIgnorable()
->identifier('method.visibility')
->line($node->getStartLine())
->build();
}

Expand Down
2 changes: 1 addition & 1 deletion src/Rules/Methods/OverridingMethodRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array
}

if ($checkVisibility) {
$messages = array_merge($messages, $this->methodVisibilityComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method));
$messages = array_merge($messages, $this->methodVisibilityComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method, $node->getOriginalNode()->name));
}

$prototypeVariants = $prototype->getVariants();
Expand Down
12 changes: 12 additions & 0 deletions tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -853,4 +853,16 @@ public function testFixWithTabs(): void
$this->fix(__DIR__ . '/data/fix-with-tabs.php', __DIR__ . '/data/fix-with-tabs.php.fixed');
}

#[RequiresPhp('>= 8.0')]
public function testBug14398(): void
{
$this->phpVersionId = PHP_VERSION_ID;
$this->analyse([__DIR__ . '/data/bug-14398.php'], [
[
'Private method Bug14398\ChildPrivateOverridesProtected::calculate() overriding protected method Bug14398\BaseProtectedMethod::calculate() should be protected or public.',
17,
],
]);
}

}
21 changes: 21 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-14398.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php // lint >= 8.0

namespace Bug14398;

class BaseProtectedMethod
{
protected function calculate(): int
{
return 42;
}
}

class ChildPrivateOverridesProtected extends BaseProtectedMethod
{
// PHPStan: Private method … overriding protected method … should be protected or public.
#[Override]
private function calculate(): int
{
return 99;
}
}
Loading