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

Fix #1475 - allow self params in traits

This commit is contained in:
Matthew Brown 2019-03-17 11:31:04 -04:00
parent f5c6abb6a0
commit f66af3e267
4 changed files with 74 additions and 28 deletions

View File

@ -359,19 +359,16 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
);
}
if ($function_param->type) {
if ($function_param->type_location) {
if ($function_param->type->check(
$this,
$function_param->type_location,
$storage->suppressed_issues,
[],
false
) === false) {
$check_stmts = false;
}
}
if ($signature_type) {
$signature_type = ExpressionAnalyzer::fleshOutType(
$codebase,
$signature_type,
$context->self,
$context->self
);
}
if ($function_param->type) {
$is_signature_type = $function_param->type === $function_param->signature_type;
if ($is_signature_type
@ -390,6 +387,18 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
$context->self,
$context->self
);
if ($function_param->type_location) {
if ($param_type->check(
$this,
$function_param->type_location,
$storage->suppressed_issues,
[],
false
) === false) {
$check_stmts = false;
}
}
} else {
if (!$non_null_param_types && isset($implemented_docblock_param_types[$offset])) {
$param_type = clone $implemented_docblock_param_types[$offset];

View File

@ -727,22 +727,42 @@ class MethodAnalyzer extends FunctionLikeAnalyzer
if ($prevent_method_signature_mismatch
&& $guide_classlike_storage->user_defined
&& $implementer_param->signature_type
&& !TypeAnalyzer::isContainedByInPhp($guide_param->signature_type, $implementer_param->signature_type)
) {
if (IssueBuffer::accepts(
new MethodSignatureMismatch(
'Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' .
$implementer_param->signature_type . '\', expecting \'' .
$guide_param->signature_type . '\' as defined by ' .
$cased_guide_method_id,
$implementer_method_storage->params[$i]->location
?: $code_location
$guide_param_signature_type = $guide_param->signature_type
? ExpressionAnalyzer::fleshOutType(
$codebase,
$guide_param->signature_type,
$guide_classlike_storage->name,
$guide_classlike_storage->name
)
)) {
return false;
}
: null;
return null;
$implementer_param_signature_type = ExpressionAnalyzer::fleshOutType(
$codebase,
$implementer_param->signature_type,
$implementer_classlike_storage->name,
$implementer_classlike_storage->name
);
if (!TypeAnalyzer::isContainedByInPhp(
$guide_param_signature_type,
$implementer_param_signature_type
)) {
if (IssueBuffer::accepts(
new MethodSignatureMismatch(
'Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' .
$implementer_param_signature_type . '\', expecting \'' .
$guide_param_signature_type . '\' as defined by ' .
$cased_guide_method_id,
$implementer_method_storage->params[$i]->location
?: $code_location
)
)) {
return false;
}
return null;
}
}
if ($guide_classlike_storage->user_defined

View File

@ -2139,10 +2139,15 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
} elseif ($param_typehint instanceof PhpParser\Node\Name\FullyQualified) {
$param_type_string = (string)$param_typehint;
$this->codebase->scanner->queueClassLikeForScanning($param_type_string, $this->file_path);
} elseif (strtolower($param_typehint->parts[0]) === 'self') {
$param_type_string = $this->fq_classlike_names[count($this->fq_classlike_names) - 1];
} else {
$param_type_string = ClassLikeAnalyzer::getFQCLNFromNameObject($param_typehint, $this->aliases);
if ($this->classlike_storages
&& strtolower($param_typehint->parts[0]) === 'self'
&& !end($this->classlike_storages)->is_trait
) {
$param_type_string = $this->fq_classlike_names[count($this->fq_classlike_names) - 1];
} else {
$param_type_string = ClassLikeAnalyzer::getFQCLNFromNameObject($param_typehint, $this->aliases);
}
if (!in_array(strtolower($param_type_string), ['self', 'static', 'parent'], true)) {
$this->codebase->scanner->queueClassLikeForScanning($param_type_string, $this->file_path);

View File

@ -839,6 +839,18 @@ class TraitTest extends TestCase
public function bar() { return []; }
}'
],
'traitSelfParam' => [
'<?php
trait T {
public function bar(self $object): self {
return $this;
}
}
class Foo {
use T;
}',
],
];
}