1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 17:52:45 +01:00

Warn if @method annotation contradicts concrete function

Fixes #5990
This commit is contained in:
robchett 2023-11-09 15:26:38 +00:00
parent 975d59032b
commit ac465067e3
2 changed files with 50 additions and 0 deletions

View File

@ -23,6 +23,8 @@ use Psalm\Issue\ImplementedReturnTypeMismatch;
use Psalm\Issue\LessSpecificImplementedReturnType; use Psalm\Issue\LessSpecificImplementedReturnType;
use Psalm\Issue\MethodSignatureMismatch; use Psalm\Issue\MethodSignatureMismatch;
use Psalm\Issue\MethodSignatureMustProvideReturnType; use Psalm\Issue\MethodSignatureMustProvideReturnType;
use Psalm\Issue\MismatchingDocblockParamType;
use Psalm\Issue\MismatchingDocblockReturnType;
use Psalm\Issue\MissingImmutableAnnotation; use Psalm\Issue\MissingImmutableAnnotation;
use Psalm\Issue\MoreSpecificImplementedParamType; use Psalm\Issue\MoreSpecificImplementedParamType;
use Psalm\Issue\OverriddenMethodAccess; use Psalm\Issue\OverriddenMethodAccess;
@ -254,6 +256,9 @@ final class MethodComparator
); );
$overridden_method_ids = $codebase->methods->getOverriddenMethodIds($pseudo_method_id); $overridden_method_ids = $codebase->methods->getOverriddenMethodIds($pseudo_method_id);
if (isset($class_storage->methods[$pseudo_method_id->method_name])) {
$overridden_method_ids[$class_storage->name] = $pseudo_method_id;
}
if ($overridden_method_ids if ($overridden_method_ids
&& $pseudo_method_name !== '__construct' && $pseudo_method_name !== '__construct'
@ -871,6 +876,18 @@ final class MethodComparator
), ),
$suppressed_issues + $implementer_classlike_storage->suppressed_issues, $suppressed_issues + $implementer_classlike_storage->suppressed_issues,
); );
} elseif ($guide_class_name == $implementer_called_class_name) {
IssueBuffer::maybeAdd(
new MismatchingDocblockParamType(
'Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id
. ' has wrong type \'' .
$implementer_method_storage_param_type->getId() . '\' in @method annotation, expecting \'' .
$guide_method_storage_param_type->getId() . '\'',
$implementer_method_storage->params[$i]->location
?: $code_location,
),
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
);
} else { } else {
IssueBuffer::maybeAdd( IssueBuffer::maybeAdd(
new ImplementedParamTypeMismatch( new ImplementedParamTypeMismatch(
@ -1092,6 +1109,17 @@ final class MethodComparator
), ),
$suppressed_issues + $implementer_classlike_storage->suppressed_issues, $suppressed_issues + $implementer_classlike_storage->suppressed_issues,
); );
} elseif ($guide_class_name == $implementer_called_class_name) {
IssueBuffer::maybeAdd(
new MismatchingDocblockReturnType(
'The inherited return type \'' . $guide_method_storage_return_type->getId()
. '\' for ' . $cased_guide_method_id . ' is different to the corresponding '
. '@method annotation \'' . $implementer_method_storage_return_type->getId() . '\'',
$implementer_method_storage->return_type_location
?: $code_location,
),
$suppressed_issues + $implementer_classlike_storage->suppressed_issues,
);
} else { } else {
IssueBuffer::maybeAdd( IssueBuffer::maybeAdd(
new ImplementedReturnTypeMismatch( new ImplementedReturnTypeMismatch(

View File

@ -1639,6 +1639,28 @@ class MethodSignatureTest extends TestCase
', ',
'error_message' => 'MethodSignatureMismatch', 'error_message' => 'MethodSignatureMismatch',
], ],
'methodAnnotationReturnMismatch' => [
'code' => '<?php
/**
* @method array bar()
*/
interface Foo
{
public function bar(): string;
}',
'error_message' => 'MismatchingDocblockReturnType',
],
'methodAnnotationParamMismatch' => [
'code' => '<?php
/**
* @method string bar(string $i)
*/
interface Foo
{
public function bar(int $i): string;
}',
'error_message' => 'MismatchingDocblockParamType',
],
]; ];
} }
} }