1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Inherit parameters via @inheritdoc

This commit is contained in:
Matthew Brown 2018-12-21 11:01:24 -05:00
parent e744e71946
commit e89425ad68
6 changed files with 55 additions and 2 deletions

View File

@ -390,6 +390,10 @@ class CommentAnalyzer
}
}
if (strpos(strtolower($comments['description']), '@inheritdoc') !== false) {
$info->inheritdoc = true;
}
if (isset($comments['specials']['template']) || isset($comments['specials']['psalm-template'])) {
$all_templates = (isset($comments['specials']['template']) ? $comments['specials']['template'] : [])
+ (isset($comments['specials']['psalm-template']) ? $comments['specials']['psalm-template'] : []);

View File

@ -206,7 +206,13 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
);
foreach ($parent_method_storage->params as $i => $guide_param) {
if ($guide_param->type && !($guide_param->signature_type && $parent_storage->user_defined)) {
if ($guide_param->type
&& (!$guide_param->signature_type
|| ($guide_param->signature_type !== $guide_param->type
&& $storage->inheritdoc)
|| !$parent_storage->user_defined
)
) {
$implemented_docblock_param_types[$i] = $guide_param->type;
}
}
@ -291,7 +297,17 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
);
}
$param_type = clone $function_param->type;
$is_signature_type = $function_param->type === $function_param->signature_type;
if ($is_signature_type
&& $storage instanceof MethodStorage
&& $storage->inheritdoc
&& isset($implemented_docblock_param_types[$offset])
) {
$param_type = clone $implemented_docblock_param_types[$offset];
} else {
$param_type = clone $function_param->type;
}
$param_type = ExpressionAnalyzer::fleshOutType(
$codebase,

View File

@ -98,4 +98,9 @@ class FunctionDocblockComment
* @var array<int, array{type: string, param_name: string}>
*/
public $if_false_assertions = [];
/**
* @var bool
*/
public $inheritdoc = false;
}

View File

@ -1250,6 +1250,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
return $storage;
}
if ($storage instanceof MethodStorage && $docblock_info->inheritdoc) {
$storage->inheritdoc = true;
}
$template_types = $class_storage && $class_storage->template_types ? $class_storage->template_types : null;
if ($docblock_info->templates) {

View File

@ -44,4 +44,9 @@ class MethodStorage extends FunctionLikeStorage
* @var bool
*/
public $overridden_somewhere = false;
/**
* @var bool
*/
public $inheritdoc = false;
}

View File

@ -506,6 +506,25 @@ class InterfaceTest extends TestCase
}
}',
],
'docblockParamInheritance' => [
'<?php
interface I {
/** @param string[] $f */
function foo(array $f) : void {}
}
class C implements I {
/** @var string[] */
private $f = [];
/**
* {@inheritdoc}
*/
public function foo(array $f) : void {
$this->f = $f;
}
}',
],
];
}