Skip to content

Commit

Permalink
Fix #4803 - always derive method params the same way
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Dec 8, 2020
1 parent 387ab14 commit 1e0bcc1
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 89 deletions.
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Expand Up @@ -953,6 +953,8 @@ public function analyze(
}
}



$plugin_classes = $codebase->config->after_classlike_checks;

if ($plugin_classes) {
Expand Down
112 changes: 23 additions & 89 deletions src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
Expand Up @@ -177,8 +177,6 @@ public function analyze(
$codebase = $this->codebase;
$project_analyzer = $this->getProjectAnalyzer();

$implemented_docblock_param_types = [];

$classlike_storage_provider = $codebase->classlike_storage_provider;

if ($codebase->track_unused_suppressions && !isset($storage->suppressed_issues[0])) {
Expand Down Expand Up @@ -345,20 +343,6 @@ public function analyze(
$storage->suppressed_issues
);
}

foreach ($parent_method_storage->params as $i => $guide_param) {
if ($guide_param->type
&& (!$guide_param->signature_type
|| ($guide_param->signature_type !== $guide_param->type
&& $storage->inheritdoc)
|| !$parent_storage->user_defined
)
) {
if (!isset($implemented_docblock_param_types[$i])) {
$implemented_docblock_param_types[$i] = $guide_param->type;
}
}
}
}
}

Expand Down Expand Up @@ -485,41 +469,6 @@ public function analyze(

$params = $storage->params;

if ($storage instanceof MethodStorage) {
$non_null_param_types = array_filter(
$storage->params,
function (FunctionLikeParameter $p): bool {
return $p->type !== null && $p->has_docblock_type;
}
);
} else {
$non_null_param_types = array_filter(
$storage->params,
function (FunctionLikeParameter $p): bool {
return $p->type !== null;
}
);
}

if ($storage instanceof MethodStorage
&& $method_id instanceof \Psalm\Internal\MethodIdentifier
&& $overridden_method_ids
) {
$types_without_docblocks = array_filter(
$storage->params,
function (FunctionLikeParameter $p): bool {
return !$p->type || !$p->has_docblock_type;
}
);

if ($types_without_docblocks) {
$params = $codebase->methods->getMethodParams(
$method_id,
$this
);
}
}

if ($codebase->alter_code) {
$this->alterParams($codebase, $storage, $params, $context);
}
Expand All @@ -544,14 +493,22 @@ function (FunctionLikeParameter $p): bool {
}
}

if ($storage instanceof MethodStorage
&& $method_id instanceof \Psalm\Internal\MethodIdentifier
&& $overridden_method_ids
) {
$params = $codebase->methods->getMethodParams(
$method_id,
$this
);
}

$check_stmts = $this->processParams(
$statements_analyzer,
$storage,
$cased_method_id,
$params,
$context,
$implemented_docblock_param_types,
(bool) $non_null_param_types,
(bool) $template_types
);

Expand Down Expand Up @@ -719,11 +676,10 @@ function (FunctionLikeParameter $p): bool {

$this->examineParamTypes($statements_analyzer, $context, $codebase);

foreach ($storage->params as $offset => $function_param) {
foreach ($params as $function_param) {
// only complain if there's no type defined by a parent type
if (!$function_param->type
&& $function_param->location
&& !isset($implemented_docblock_param_types[$offset])
) {
if ($this->function instanceof Closure
|| $this->function instanceof ArrowFunction
Expand Down Expand Up @@ -1147,16 +1103,13 @@ private function checkParamReferences(

/**
* @param array<int, \Psalm\Storage\FunctionLikeParameter> $params
* @param array<int, Type\Union> $implemented_docblock_param_types
*/
private function processParams(
StatementsAnalyzer $statements_analyzer,
FunctionLikeStorage $storage,
?string $cased_method_id,
array $params,
Context $context,
array $implemented_docblock_param_types,
bool $non_null_param_types,
bool $has_template_types
) : bool {
$check_stmts = true;
Expand Down Expand Up @@ -1193,17 +1146,7 @@ private function processParams(
}

if ($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 = clone $function_param->type;

$param_type = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
Expand All @@ -1227,29 +1170,20 @@ private function processParams(
$check_stmts = false;
}
}
} else {
if (!$non_null_param_types && isset($implemented_docblock_param_types[$offset])) {
$param_type = clone $implemented_docblock_param_types[$offset];

$param_type = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
$param_type,
$context->self,
$context->self,
$this->getParentFQCLN()
);
} else {
$param_type = Type::getMixed();
}
}

if ($param_type->hasTemplate() && $param_type->isSingle()) {
/** @var Type\Atomic\TTemplateParam */
$template_type = \array_values($param_type->getAtomicTypes())[0];
if (!$storage instanceof MethodStorage
&& $param_type->hasTemplate()
&& $param_type->isSingle()
) {
/** @var Type\Atomic\TTemplateParam */
$template_type = \array_values($param_type->getAtomicTypes())[0];

if ($template_type->as->getTemplateTypes()) {
$param_type = $template_type->as;
if ($template_type->as->getTemplateTypes()) {
$param_type = $template_type->as;
}
}
} else {
$param_type = Type::getMixed();
}

$var_type = $param_type;
Expand Down
20 changes: 20 additions & 0 deletions tests/Template/ClassTemplateExtendsTest.php
Expand Up @@ -5301,6 +5301,26 @@ function second(C $c) : void {
}',
'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'
],
];
}
}

0 comments on commit 1e0bcc1

Please sign in to comment.