1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Be smarter when choosing inherited param types

Ref #4803
This commit is contained in:
Matt Brown 2020-12-10 00:15:37 -05:00 committed by Daniil Gentili
parent 3e2d998cfe
commit d64c49be92
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
5 changed files with 55 additions and 27 deletions

View File

@ -311,14 +311,9 @@ class Populator
$declaring_method_storage = $declaring_class_storage->methods[$declaring_method_name];
if (($declaring_method_storage->has_docblock_param_types
|| $declaring_method_storage->return_type
!== $declaring_method_storage->signature_return_type)
|| $declaring_method_storage->has_docblock_return_type)
&& !$method_storage->has_docblock_param_types
&& $method_storage->return_type === $method_storage->signature_return_type
&& (!$declaring_method_storage->signature_return_type
|| ($method_storage->signature_return_type
&& $method_storage->signature_return_type->getId()
=== $declaring_method_storage->signature_return_type->getId()))
&& !$method_storage->has_docblock_return_type
&& $method_storage->inherited_return_type !== null
) {
if (!isset($storage->documenting_method_ids[$method_name])

View File

@ -868,6 +868,10 @@ class FunctionLikeDocblockScanner
$storage->return_type->setFromDocblock();
if ($storage instanceof MethodStorage) {
$storage->has_docblock_return_type = true;
}
if ($storage->signature_return_type) {
$all_typehint_types_match = true;
$signature_return_atomic_types = $storage->signature_return_type->getAtomicTypes();
@ -882,6 +886,10 @@ class FunctionLikeDocblockScanner
if ($all_typehint_types_match) {
$storage->return_type->from_docblock = false;
if ($storage instanceof MethodStorage) {
$storage->has_docblock_return_type = true;
}
}
if ($storage->signature_return_type->isNullable()

View File

@ -60,6 +60,11 @@ class MethodStorage extends FunctionLikeStorage
*/
public $has_docblock_param_types = false;
/**
* @var bool
*/
public $has_docblock_return_type = false;
/**
* @var bool
*/

View File

@ -847,6 +847,28 @@ class MethodSignatureTest extends TestCase
public function foo(): void {}
}'
],
'inheritParamTypeWhenSignatureReturnTypeChanged' => [
'<?php
class A {
public function __construct(string $s) {}
}
class AChild extends A {}
interface B {
/** @param string $data */
public function create($data): A;
}
class C implements B {
public function create($data): AChild {
return new AChild($data);
}
}',
[],
[],
'7.4'
],
];
}

View File

@ -4222,6 +4222,24 @@ class ClassTemplateExtendsTest extends TestCase
public function at($k) { /** @var Tv */ return 1; }
}'
],
'inheritSubstitutedParamFromInterface' => [
'<?php
/** @psalm-template T */
interface BuilderInterface {
/** @psalm-param T $data */
public function create($data): Exception;
}
/** @implements BuilderInterface<string> */
class CovariantUserBuilder implements BuilderInterface {
public function create($data): RuntimeException {
return new RuntimeException($data);
}
}',
[],
[],
'7.4'
],
];
}
@ -5301,26 +5319,6 @@ class ClassTemplateExtendsTest extends TestCase
}',
'error_message' => 'ArgumentTypeCoercion'
],
'inheritSubstitutedParamFromInterface' => [
'<?php
/** @psalm-template T */
interface BuilderInterface {
/** @psalm-param T $data */
public function create($data): Exception;
}
/** @implements BuilderInterface<string> */
class CovariantUserBuilder implements BuilderInterface {
public function create($data): RuntimeException {
/** @psalm-suppress MixedArgument */
return new RuntimeException($data);
}
}',
'error_message' => 'MissingParamType',
[],
false,
'7.4'
],
];
}
}