1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Delay checks for MissingPropertyType so we can give more useful messages

This commit is contained in:
Matthew Brown 2017-04-14 23:09:34 -04:00
parent ce6ca58291
commit 60be6f07a0
4 changed files with 78 additions and 33 deletions

View File

@ -605,6 +605,12 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
);
}
}
foreach ($trait_checker->class->stmts as $trait_stmt) {
if ($trait_stmt instanceof PhpParser\Node\Stmt\Property) {
$this->checkForMissingPropertyType($trait_stmt);
}
}
}
}
}
@ -688,7 +694,11 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
}
}
foreach ($this->class->stmts as $stmt) {
if ($stmt instanceof PhpParser\Node\Stmt\Property) {
$this->checkForMissingPropertyType($stmt);
}
}
}
/**
@ -1012,17 +1022,6 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
// fall through
}
}
} elseif (!$comment || !$comment->getText()) {
if (IssueBuffer::accepts(
new MissingPropertyType(
'Property ' . $this->fq_class_name . '::$' . $stmt->props[0]->name . ' does not have a ' .
'declared type',
new CodeLocation($this, $stmt)
),
$this->source->getSuppressedIssues()
)) {
// fall through
}
}
$property_group_type = $type_in_comment ?: null;
@ -1075,6 +1074,41 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
}
}
/**
* @param PhpParser\Node\Stmt\Property $stmt
* @return void
*/
private function checkForMissingPropertyType(PhpParser\Node\Stmt\Property $stmt)
{
$comment = $stmt->getDocComment();
$type_in_comment = null;
$property_type_line_number = null;
$storage = self::$storage[strtolower($this->fq_class_name)];
if (!$comment || !$comment->getText()) {
$fq_class_name = $this->fq_class_name;
$property_name = $stmt->props[0]->name;
$message = 'Property ' . $fq_class_name . '::$' . $property_name . ' does not have a declared type';
$property_storage = ClassLikeChecker::$storage[strtolower($fq_class_name)]->properties[$property_name];
if ($property_storage->suggested_type) {
$message .= ' - consider ' . $property_storage->suggested_type;
}
if (IssueBuffer::accepts(
new MissingPropertyType(
$message,
new CodeLocation($this, $stmt)
),
$this->source->getSuppressedIssues()
)) {
// fall through
}
}
}
/**
* @param PhpParser\Node\Stmt\ClassConst $stmt
* @param Context $class_context

View File

@ -671,18 +671,19 @@ class AssignmentChecker
$class_property_type = $property_storage->type;
if ($class_property_type === false) {
if (IssueBuffer::accepts(
new MissingPropertyType(
'Property ' . $lhs_type_part->value . '::$' . $prop_name . ' does not have a declared ' .
'type',
new CodeLocation($statements_checker->getSource(), $stmt)
),
$statements_checker->getSuppressedIssues()
)) {
// fall through
$class_property_type = Type::getMixed();
if (!$assignment_value_type->isMixed()) {
if ($property_storage->suggested_type) {
$property_storage->suggested_type = Type::combineUnionTypes(
$assignment_value_type,
$property_storage->suggested_type
);
} else {
$property_storage->suggested_type = $assignment_value_type;
}
}
$class_property_type = Type::getMixed();
} else {
$class_property_type = ExpressionChecker::fleshOutTypes(
clone $class_property_type,
@ -848,17 +849,18 @@ class AssignmentChecker
$class_property_type = $property_storage->type;
if ($class_property_type === false) {
if (IssueBuffer::accepts(
new MissingPropertyType(
'Property ' . $fq_class_name . '::$' . $prop_name . ' does not have a declared type',
new CodeLocation($statements_checker->getSource(), $stmt)
),
$statements_checker->getSuppressedIssues()
)) {
// fall through
}
$class_property_type = Type::getMixed();
if (!$assignment_value_type->isMixed()) {
if ($property_storage->suggested_type) {
$property_storage->suggested_type = Type::combineUnionTypes(
$assignment_value_type,
$property_storage->suggested_type
);
} else {
$property_storage->suggested_type = $assignment_value_type;
}
}
} else {
$class_property_type = clone $class_property_type;
}

View File

@ -31,6 +31,11 @@ class PropertyStorage
*/
public $type;
/**
* @var Type\Union|null
*/
public $suggested_type;
/**
* @var bool
*/

View File

@ -206,7 +206,7 @@ class PropertyTypeTest extends PHPUnit_Framework_TestCase
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage MissingPropertyType
* @expectedExceptionMessage MissingPropertyType - somefile.php:3 - Property A::$foo does not have a declared type - consider int
* @return void
*/
public function testMissingPropertyType()
@ -214,6 +214,10 @@ class PropertyTypeTest extends PHPUnit_Framework_TestCase
$stmts = self::$parser->parse('<?php
class A {
public $foo;
public function assignToFoo() : void {
$this->foo = 5;
}
}
');