Skip to content

Commit 5fd8cee

Browse files
committed
MethodSignatureRule - look at abstract trait method in Bleeding Edge
1 parent 2df14af commit 5fd8cee

8 files changed

+78
-3
lines changed

Diff for: conf/bleedingEdge.neon

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ parameters:
2020
notAnalysedTrait: true
2121
curlSetOptTypes: true
2222
listType: true
23+
abstractTraitMethod: true
2324
missingMagicSerializationRule: true
2425
nullContextForVoidReturningFunctions: true
2526
unescapeStrings: true

Diff for: conf/config.neon

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ parameters:
5454
notAnalysedTrait: false
5555
curlSetOptTypes: false
5656
listType: false
57+
abstractTraitMethod: false
5758
missingMagicSerializationRule: false
5859
nullContextForVoidReturningFunctions: false
5960
unescapeStrings: false
@@ -916,6 +917,7 @@ services:
916917
arguments:
917918
reportMaybes: %reportMaybesInMethodSignatures%
918919
reportStatic: %reportStaticMethodSignatures%
920+
abstractTraitMethod: %featureToggles.abstractTraitMethod%
919921

920922
-
921923
class: PHPStan\Rules\Methods\MethodParameterComparisonHelper

Diff for: conf/parametersSchema.neon

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ parametersSchema:
5050
notAnalysedTrait: bool()
5151
curlSetOptTypes: bool()
5252
listType: bool()
53+
abstractTraitMethod: bool()
5354
missingMagicSerializationRule: bool()
5455
nullContextForVoidReturningFunctions: bool()
5556
unescapeStrings: bool()

Diff for: src/PhpDoc/StubValidator.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private function getRuleRegistry(Container $container): RuleRegistry
164164
new ExistingClassesInTypehintsRule($functionDefinitionCheck),
165165
new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck),
166166
new ExistingClassesInPropertiesRule($reflectionProvider, $classCaseSensitivityCheck, $unresolvableTypeHelper, $phpVersion, true, false),
167-
new OverridingMethodRule($phpVersion, new MethodSignatureRule(true, true), true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc']),
167+
new OverridingMethodRule($phpVersion, new MethodSignatureRule(true, true, $container->getParameter('featureToggles')['abstractTraitMethod']), true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc']),
168168
new DuplicateDeclarationRule(),
169169
new LocalTypeAliasesRule($localTypeAliasesCheck),
170170
new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider),

Diff for: src/Rules/Methods/MethodSignatureRule.php

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use PHPStan\Type\TypeTraverser;
2323
use PHPStan\Type\VerbosityLevel;
2424
use function count;
25+
use function is_bool;
2526
use function min;
2627
use function sprintf;
2728

@@ -34,6 +35,7 @@ class MethodSignatureRule implements Rule
3435
public function __construct(
3536
private bool $reportMaybes,
3637
private bool $reportStatic,
38+
private bool $abstractTraitMethod,
3739
)
3840
{
3941
}
@@ -132,6 +134,24 @@ private function collectParentMethods(string $methodName, ClassReflection $class
132134
$parentMethods[] = $interface->getNativeMethod($methodName);
133135
}
134136

137+
if ($this->abstractTraitMethod) {
138+
foreach ($class->getTraits(true) as $trait) {
139+
if (!$trait->hasNativeMethod($methodName)) {
140+
continue;
141+
}
142+
143+
$method = $trait->getNativeMethod($methodName);
144+
$isAbstract = $method->isAbstract();
145+
if (is_bool($isAbstract)) {
146+
if ($isAbstract) {
147+
$parentMethods[] = $method;
148+
}
149+
} elseif ($isAbstract->yes()) {
150+
$parentMethods[] = $method;
151+
}
152+
}
153+
}
154+
135155
return $parentMethods;
136156
}
137157

Diff for: tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ protected function getRule(): Rule
2323

2424
return new OverridingMethodRule(
2525
$phpVersion,
26-
new MethodSignatureRule($this->reportMaybes, $this->reportStatic),
26+
new MethodSignatureRule($this->reportMaybes, $this->reportStatic, true),
2727
true,
2828
new MethodParameterComparisonHelper($phpVersion, true),
2929
true,
@@ -423,4 +423,17 @@ public function testBug9905(): void
423423
$this->analyse([__DIR__ . '/data/bug-9905.php'], []);
424424
}
425425

426+
public function testTraits(): void
427+
{
428+
$this->reportMaybes = true;
429+
$this->reportStatic = true;
430+
431+
$this->analyse([__DIR__ . '/data/overriding-trait-methods-phpdoc.php'], [
432+
[
433+
'Parameter #1 $i (non-empty-string) of method OverridingTraitMethodsPhpDoc\Bar::doBar() should be contravariant with parameter $i (string) of method OverridingTraitMethodsPhpDoc\Foo::doBar()',
434+
33,
435+
]
436+
]);
437+
}
438+
426439
}

Diff for: tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ protected function getRule(): Rule
2323

2424
return new OverridingMethodRule(
2525
$phpVersion,
26-
new MethodSignatureRule(true, true),
26+
new MethodSignatureRule(true, true, true),
2727
false,
2828
new MethodParameterComparisonHelper($phpVersion, true),
2929
true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php // lint >= 8.0
2+
3+
namespace OverridingTraitMethodsPhpDoc;
4+
5+
trait Foo
6+
{
7+
8+
public function doFoo(int $i): int
9+
{
10+
11+
}
12+
13+
abstract public function doBar(string $i): int;
14+
15+
}
16+
17+
class Bar
18+
{
19+
20+
use Foo;
21+
22+
/**
23+
* @param positive-int $i
24+
*/
25+
public function doFoo(int $i): string
26+
{
27+
// ok, trait method not abstract
28+
}
29+
30+
/**
31+
* @param non-empty-string $i
32+
*/
33+
public function doBar(string $i): int
34+
{
35+
// error
36+
}
37+
38+
}

0 commit comments

Comments
 (0)