Skip to content

Commit ac46506

Browse files
committed
Warn if @method annotation contradicts concrete function
Fixes vimeo#5990
1 parent 975d590 commit ac46506

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

src/Psalm/Internal/Analyzer/MethodComparator.php

+28
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
use Psalm\Issue\LessSpecificImplementedReturnType;
2424
use Psalm\Issue\MethodSignatureMismatch;
2525
use Psalm\Issue\MethodSignatureMustProvideReturnType;
26+
use Psalm\Issue\MismatchingDocblockParamType;
27+
use Psalm\Issue\MismatchingDocblockReturnType;
2628
use Psalm\Issue\MissingImmutableAnnotation;
2729
use Psalm\Issue\MoreSpecificImplementedParamType;
2830
use Psalm\Issue\OverriddenMethodAccess;
@@ -254,6 +256,9 @@ public static function comparePseudoMethods(
254256
);
255257

256258
$overridden_method_ids = $codebase->methods->getOverriddenMethodIds($pseudo_method_id);
259+
if (isset($class_storage->methods[$pseudo_method_id->method_name])) {
260+
$overridden_method_ids[$class_storage->name] = $pseudo_method_id;
261+
}
257262

258263
if ($overridden_method_ids
259264
&& $pseudo_method_name !== '__construct'
@@ -871,6 +876,18 @@ private static function compareMethodDocblockParams(
871876
),
872877
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
873878
);
879+
} elseif ($guide_class_name == $implementer_called_class_name) {
880+
IssueBuffer::maybeAdd(
881+
new MismatchingDocblockParamType(
882+
'Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id
883+
. ' has wrong type \'' .
884+
$implementer_method_storage_param_type->getId() . '\' in @method annotation, expecting \'' .
885+
$guide_method_storage_param_type->getId() . '\'',
886+
$implementer_method_storage->params[$i]->location
887+
?: $code_location,
888+
),
889+
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
890+
);
874891
} else {
875892
IssueBuffer::maybeAdd(
876893
new ImplementedParamTypeMismatch(
@@ -1092,6 +1109,17 @@ private static function compareMethodDocblockReturnTypes(
10921109
),
10931110
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
10941111
);
1112+
} elseif ($guide_class_name == $implementer_called_class_name) {
1113+
IssueBuffer::maybeAdd(
1114+
new MismatchingDocblockReturnType(
1115+
'The inherited return type \'' . $guide_method_storage_return_type->getId()
1116+
. '\' for ' . $cased_guide_method_id . ' is different to the corresponding '
1117+
. '@method annotation \'' . $implementer_method_storage_return_type->getId() . '\'',
1118+
$implementer_method_storage->return_type_location
1119+
?: $code_location,
1120+
),
1121+
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
1122+
);
10951123
} else {
10961124
IssueBuffer::maybeAdd(
10971125
new ImplementedReturnTypeMismatch(

tests/MethodSignatureTest.php

+22
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,28 @@ public function foo(): int {
16391639
',
16401640
'error_message' => 'MethodSignatureMismatch',
16411641
],
1642+
'methodAnnotationReturnMismatch' => [
1643+
'code' => '<?php
1644+
/**
1645+
* @method array bar()
1646+
*/
1647+
interface Foo
1648+
{
1649+
public function bar(): string;
1650+
}',
1651+
'error_message' => 'MismatchingDocblockReturnType',
1652+
],
1653+
'methodAnnotationParamMismatch' => [
1654+
'code' => '<?php
1655+
/**
1656+
* @method string bar(string $i)
1657+
*/
1658+
interface Foo
1659+
{
1660+
public function bar(int $i): string;
1661+
}',
1662+
'error_message' => 'MismatchingDocblockParamType',
1663+
],
16421664
];
16431665
}
16441666
}

0 commit comments

Comments
 (0)