diff --git a/src/Node/InClassMethodNode.php b/src/Node/InClassMethodNode.php index 6547b7a12a9..329f657b017 100644 --- a/src/Node/InClassMethodNode.php +++ b/src/Node/InClassMethodNode.php @@ -19,7 +19,12 @@ public function __construct( private Node\Stmt\ClassMethod $originalNode, ) { - parent::__construct($originalNode->getAttributes()); + $attributes = $originalNode->getAttributes(); + $nameStartLine = $originalNode->name->getStartLine(); + if ($nameStartLine >= $originalNode->getStartLine() && $nameStartLine <= $originalNode->getEndLine()) { + $attributes['startLine'] = $nameStartLine; + } + parent::__construct($attributes); } public function getClassReflection(): ClassReflection diff --git a/tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php b/tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php index aef982a7d73..6fc35b859da 100644 --- a/tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php +++ b/tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php @@ -99,15 +99,15 @@ public function testMethodRule(): void ], [ 'Deprecated', - 15, + 16, ], [ 'Deprecated: msg', - 21, + 22, ], [ 'Deprecated: msg2', - 27, + 28, ], ]); } diff --git a/tests/PHPStan/Reflection/AttributeReflectionFromNodeRuleTest.php b/tests/PHPStan/Reflection/AttributeReflectionFromNodeRuleTest.php index a07cbead1b2..f79880e9779 100644 --- a/tests/PHPStan/Reflection/AttributeReflectionFromNodeRuleTest.php +++ b/tests/PHPStan/Reflection/AttributeReflectionFromNodeRuleTest.php @@ -86,7 +86,7 @@ public function testRule(): void $this->analyse([__DIR__ . '/data/attribute-reflection.php'], [ [ '#[AttributeReflectionTest\MyAttr(one: 7, two: 8)], $test: #[AttributeReflectionTest\MyAttr(one: 9, two: 10)]', - 28, + 29, ], [ '#[AttributeReflectionTest\MyAttr()]', diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index 87319aa44dd..d8bca55b6fc 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -221,15 +221,15 @@ public function testBug3997(): void $this->analyse([__DIR__ . '/data/bug-3997.php'], [ [ 'Return type (int) of method Bug3997\Baz::count() should be covariant with return type (int<0, max>) of method Countable::count()', - 35, + 36, ], [ 'Return type (int) of method Bug3997\Lorem::count() should be covariant with return type (int<0, max>) of method Countable::count()', - 49, + 50, ], [ 'Return type (string) of method Bug3997\Ipsum::count() should be compatible with return type (int<0, max>) of method Countable::count()', - 63, + 64, ], ]); } diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 55979eeb77d..9603b2ee52e 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -659,7 +659,7 @@ public function testBug10101(): void $this->analyse([__DIR__ . '/data/bug-10101.php'], [ [ 'Return type mixed of method Bug10101\B::next() is not covariant with return type void of method Bug10101\A::next().', - 10, + 11, ], ]); } @@ -690,7 +690,7 @@ public function testBug10149(): void $errors = [ [ 'Method Bug10149\StdSat::__get() has #[\Override] attribute but does not override any method.', - 10, + 11, ], ]; $this->analyse([__DIR__ . '/data/bug-10149.php'], $errors); @@ -729,11 +729,11 @@ public function testOverrideAttribute(): void $this->analyse([__DIR__ . '/data/override-attribute.php'], [ [ 'Method OverrideAttribute\Bar::test2() has #[\Override] attribute but does not override any method.', - 24, + 25, ], [ 'Method OverrideAttribute\ChildOfParentWithConstructor::__construct() has #[\Override] attribute but does not override any method.', - 42, + 43, ], ]); } @@ -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, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-14398.php b/tests/PHPStan/Rules/Methods/data/bug-14398.php new file mode 100644 index 00000000000..f9fbae4dd22 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-14398.php @@ -0,0 +1,21 @@ += 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; + } +}