Skip to content

Commit c6432ed

Browse files
phpstan-botclaude
andcommitted
Fix InClassMethodNode startLine for all rules with attributes
Instead of fixing individual rules, adjust InClassMethodNode to use the method name's start line when attributes shift the node's start line. This fixes incorrect error line numbers for ALL rules processing InClassMethodNode when methods have attributes (e.g. #[Override]). The range check ensures trait-aliased methods (where the name identifier points to the alias location) keep their original line number. Also reverts MethodVisibilityComparisonHelper to its simpler signature since the line fix is now handled at the node level. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ce81771 commit c6432ed

File tree

8 files changed

+20
-18
lines changed

8 files changed

+20
-18
lines changed

src/Node/InClassMethodNode.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ public function __construct(
1919
private Node\Stmt\ClassMethod $originalNode,
2020
)
2121
{
22-
parent::__construct($originalNode->getAttributes());
22+
$attributes = $originalNode->getAttributes();
23+
$nameStartLine = $originalNode->name->getStartLine();
24+
if ($nameStartLine >= $originalNode->getStartLine() && $nameStartLine <= $originalNode->getEndLine()) {
25+
$attributes['startLine'] = $nameStartLine;
26+
}
27+
parent::__construct($attributes);
2328
}
2429

2530
public function getClassReflection(): ClassReflection

src/Rules/Methods/ConsistentConstructorRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function processNode(Node $node, Scope $scope): array
4848

4949
return array_merge(
5050
$this->methodParameterComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, true),
51-
$this->methodVisibilityComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, $node->getOriginalNode()->name),
51+
$this->methodVisibilityComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method),
5252
);
5353
}
5454

src/Rules/Methods/MethodVisibilityComparisonHelper.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\Methods;
44

5-
use PhpParser\Node;
65
use PHPStan\DependencyInjection\AutowiredService;
76
use PHPStan\Reflection\ClassReflection;
87
use PHPStan\Reflection\ExtendedMethodReflection;
@@ -16,7 +15,7 @@ final class MethodVisibilityComparisonHelper
1615
{
1716

1817
/** @return list<IdentifierRuleError> */
19-
public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, Node $node): array
18+
public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method): array
2019
{
2120
/** @var list<IdentifierRuleError> $messages */
2221
$messages = [];
@@ -33,7 +32,6 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr
3332
))
3433
->nonIgnorable()
3534
->identifier('method.visibility')
36-
->line($node->getStartLine())
3735
->build();
3836
}
3937
} elseif ($method->isPrivate()) {
@@ -46,7 +44,6 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr
4644
))
4745
->nonIgnorable()
4846
->identifier('method.visibility')
49-
->line($node->getStartLine())
5047
->build();
5148
}
5249

src/Rules/Methods/OverridingMethodRule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array
189189
}
190190

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

195195
$prototypeVariants = $prototype->getVariants();

tests/PHPStan/Reflection/Annotations/DeprecatedAttributePhpFunctionFromParserReflectionRuleTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ public function testMethodRule(): void
9999
],
100100
[
101101
'Deprecated',
102-
15,
102+
16,
103103
],
104104
[
105105
'Deprecated: msg',
106-
21,
106+
22,
107107
],
108108
[
109109
'Deprecated: msg2',
110-
27,
110+
28,
111111
],
112112
]);
113113
}

tests/PHPStan/Reflection/AttributeReflectionFromNodeRuleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function testRule(): void
8686
$this->analyse([__DIR__ . '/data/attribute-reflection.php'], [
8787
[
8888
'#[AttributeReflectionTest\MyAttr(one: 7, two: 8)], $test: #[AttributeReflectionTest\MyAttr(one: 9, two: 10)]',
89-
28,
89+
29,
9090
],
9191
[
9292
'#[AttributeReflectionTest\MyAttr()]',

tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,15 @@ public function testBug3997(): void
221221
$this->analyse([__DIR__ . '/data/bug-3997.php'], [
222222
[
223223
'Return type (int) of method Bug3997\Baz::count() should be covariant with return type (int<0, max>) of method Countable::count()',
224-
35,
224+
36,
225225
],
226226
[
227227
'Return type (int) of method Bug3997\Lorem::count() should be covariant with return type (int<0, max>) of method Countable::count()',
228-
49,
228+
50,
229229
],
230230
[
231231
'Return type (string) of method Bug3997\Ipsum::count() should be compatible with return type (int<0, max>) of method Countable::count()',
232-
63,
232+
64,
233233
],
234234
]);
235235
}

tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ public function testBug10101(): void
659659
$this->analyse([__DIR__ . '/data/bug-10101.php'], [
660660
[
661661
'Return type mixed of method Bug10101\B::next() is not covariant with return type void of method Bug10101\A::next().',
662-
10,
662+
11,
663663
],
664664
]);
665665
}
@@ -690,7 +690,7 @@ public function testBug10149(): void
690690
$errors = [
691691
[
692692
'Method Bug10149\StdSat::__get() has #[\Override] attribute but does not override any method.',
693-
10,
693+
11,
694694
],
695695
];
696696
$this->analyse([__DIR__ . '/data/bug-10149.php'], $errors);
@@ -729,11 +729,11 @@ public function testOverrideAttribute(): void
729729
$this->analyse([__DIR__ . '/data/override-attribute.php'], [
730730
[
731731
'Method OverrideAttribute\Bar::test2() has #[\Override] attribute but does not override any method.',
732-
24,
732+
25,
733733
],
734734
[
735735
'Method OverrideAttribute\ChildOfParentWithConstructor::__construct() has #[\Override] attribute but does not override any method.',
736-
42,
736+
43,
737737
],
738738
]);
739739
}

0 commit comments

Comments
 (0)