mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
This commit is contained in:
parent
1cc13bdeeb
commit
6b4bd47ddb
@ -535,7 +535,7 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
|
||||
}
|
||||
|
||||
$uninitialized_variables[] = '$this->' . $property_name;
|
||||
$uninitialized_properties[$property_name] = $property;
|
||||
$uninitialized_properties[$property_name] = $property;
|
||||
}
|
||||
|
||||
if ($uninitialized_properties) {
|
||||
|
@ -497,7 +497,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
|
||||
) {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidDocblock(
|
||||
'Return type has wrong type \'' . $storage->return_type .
|
||||
'Docblock has incorrect return type \'' . $storage->return_type .
|
||||
'\', should be \'' . $storage->signature_return_type . '\'',
|
||||
$storage->return_type_location
|
||||
),
|
||||
|
@ -56,6 +56,8 @@ class ForeachChecker
|
||||
$iterator_type = null;
|
||||
}
|
||||
|
||||
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
||||
|
||||
if ($iterator_type) {
|
||||
if ($iterator_type->isNull()) {
|
||||
if (IssueBuffer::accepts(
|
||||
@ -79,8 +81,6 @@ class ForeachChecker
|
||||
}
|
||||
}
|
||||
|
||||
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
||||
|
||||
foreach ($iterator_type->types as $iterator_type) {
|
||||
// if it's an empty array, we cannot iterate over it
|
||||
if ((string) $iterator_type === 'array<empty, empty>') {
|
||||
@ -235,7 +235,13 @@ class ForeachChecker
|
||||
);
|
||||
|
||||
if ($var_comment && $var_comment->var_id) {
|
||||
$foreach_context->vars_in_scope[$var_comment->var_id] = Type::parseString($var_comment->type);
|
||||
$comment_type = ExpressionChecker::fleshOutType(
|
||||
$project_checker,
|
||||
Type::parseString($var_comment->type),
|
||||
$context->self
|
||||
);
|
||||
|
||||
$foreach_context->vars_in_scope[$var_comment->var_id] = $comment_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ class AssignmentChecker
|
||||
);
|
||||
|
||||
$var_comment = null;
|
||||
$comment_type = null;
|
||||
|
||||
if ($doc_comment) {
|
||||
$var_comment = CommentChecker::getTypeFromComment(
|
||||
@ -88,8 +89,18 @@ class AssignmentChecker
|
||||
$came_from_line_number
|
||||
);
|
||||
|
||||
if ($var_comment && $var_comment->var_id && $var_comment->var_id !== $var_id) {
|
||||
$context->vars_in_scope[$var_comment->var_id] = Type::parseString($var_comment->type);
|
||||
if ($var_comment) {
|
||||
$comment_type = ExpressionChecker::fleshOutType(
|
||||
$statements_checker->getFileChecker()->project_checker,
|
||||
Type::parseString($var_comment->type),
|
||||
$context->self
|
||||
);
|
||||
|
||||
$comment_type->setFromDocblock();
|
||||
|
||||
if ($var_comment->var_id && $var_comment->var_id !== $var_id) {
|
||||
$context->vars_in_scope[$var_comment->var_id] = $comment_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,16 +112,16 @@ class AssignmentChecker
|
||||
|
||||
// if we're not exiting immediately, make everything mixed
|
||||
$context->vars_in_scope[$var_id] =
|
||||
$var_comment && (!$var_comment->var_id || $var_comment->var_id === $var_id)
|
||||
? Type::parseString($var_comment->type)
|
||||
$var_comment && (!$var_comment->var_id || $var_comment->var_id === $var_id) && $comment_type
|
||||
? $comment_type
|
||||
: Type::getMixed();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($var_comment && (!$var_comment->var_id || $var_comment->var_id === $var_id)) {
|
||||
$assign_value_type = $var_comment->type;
|
||||
if ($var_comment && (!$var_comment->var_id || $var_comment->var_id === $var_id) && $comment_type) {
|
||||
$assign_value_type = $comment_type;
|
||||
} elseif (!$assign_value_type) {
|
||||
if (isset($assign_value->inferredType)) {
|
||||
/** @var Type\Union */
|
||||
|
@ -1827,7 +1827,13 @@ class ExpressionChecker
|
||||
);
|
||||
|
||||
if ($var_comment && $var_comment->var_id) {
|
||||
$context->vars_in_scope[$var_comment->var_id] = Type::parseString($var_comment->type);
|
||||
$comment_type = ExpressionChecker::fleshOutType(
|
||||
$statements_checker->getFileChecker()->project_checker,
|
||||
Type::parseString($var_comment->type),
|
||||
$context->self
|
||||
);
|
||||
|
||||
$context->vars_in_scope[$var_comment->var_id] = $comment_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
}
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Return_) {
|
||||
$has_returned = true;
|
||||
$this->analyzeReturn($stmt, $context);
|
||||
$this->analyzeReturn($project_checker, $stmt, $context);
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Throw_) {
|
||||
$has_returned = true;
|
||||
$this->analyzeThrow($stmt, $context);
|
||||
@ -320,7 +320,13 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
);
|
||||
|
||||
if ($var_comment && $var_comment->var_id) {
|
||||
$context->vars_in_scope[$var_comment->var_id] = Type::parseString($var_comment->type);
|
||||
$comment_type = ExpressionChecker::fleshOutType(
|
||||
$project_checker,
|
||||
Type::parseString($var_comment->type),
|
||||
$context->self
|
||||
);
|
||||
|
||||
$context->vars_in_scope[$var_comment->var_id] = $comment_type;
|
||||
}
|
||||
}
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\Goto_) {
|
||||
@ -832,8 +838,11 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
*
|
||||
* @return false|null
|
||||
*/
|
||||
private function analyzeReturn(PhpParser\Node\Stmt\Return_ $stmt, Context $context)
|
||||
{
|
||||
private function analyzeReturn(
|
||||
ProjectChecker $project_checker,
|
||||
PhpParser\Node\Stmt\Return_ $stmt,
|
||||
Context $context
|
||||
) {
|
||||
$doc_comment_text = (string)$stmt->getDocComment();
|
||||
|
||||
$var_comment = null;
|
||||
@ -847,7 +856,13 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
);
|
||||
|
||||
if ($var_comment && $var_comment->var_id) {
|
||||
$context->vars_in_scope[$var_comment->var_id] = Type::parseString($var_comment->type);
|
||||
$comment_type = ExpressionChecker::fleshOutType(
|
||||
$project_checker,
|
||||
Type::parseString($var_comment->type),
|
||||
$context->self
|
||||
);
|
||||
|
||||
$context->vars_in_scope[$var_comment->var_id] = $comment_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,6 +715,14 @@ class TypeChecker
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof TNamedObject
|
||||
&& $input_type_part->value === 'static'
|
||||
&& $container_type_part instanceof TNamedObject
|
||||
&& $container_type_part->value === 'self'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof TNamedObject &&
|
||||
$input_type_part->value === 'Closure' &&
|
||||
$container_type_part instanceof TCallable
|
||||
|
@ -221,6 +221,19 @@ class AnnotationTest extends TestCase
|
||||
public function foo($a) : void {}
|
||||
}',
|
||||
],
|
||||
'varSelf' => [
|
||||
'<?php
|
||||
class A
|
||||
{
|
||||
public function foo() : void {}
|
||||
|
||||
public function getMeAgain() : void {
|
||||
/** @var self */
|
||||
$me = $this;
|
||||
$me->foo();
|
||||
}
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -368,6 +368,50 @@ class ReturnTypeTest extends TestCase
|
||||
function doSomething($res) : void {
|
||||
}',
|
||||
],
|
||||
'selfReturnNoTypehints' => [
|
||||
'<?php
|
||||
class A {
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function getMe()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A
|
||||
{
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function getMeAgain() {
|
||||
return $this->getMe();
|
||||
}
|
||||
}',
|
||||
],
|
||||
'selfReturnTypehints' => [
|
||||
'<?php
|
||||
class A {
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function getMe() : self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A
|
||||
{
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function getMeAgain() : self {
|
||||
return $this->getMe();
|
||||
}
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user