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

Emit issue when property type is not defined

This commit is contained in:
Matt Brown 2017-03-02 12:19:18 -05:00
parent 7f3a763303
commit f9f38f283e
6 changed files with 48 additions and 17 deletions

View File

@ -525,10 +525,9 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
$property_type = Type::getMixed();
}
// type_location is only set if collect_references is true
if ($property->type_location && !$property_type->isMixed()) {
$fleshed_out_type = ExpressionChecker::fleshOutTypes(clone $property_type, $this->fq_class_name, null);
$fleshed_out_type->check($this, $property->type_location, $this->getSuppressedIssues());
$fleshed_out_type->check($this, $property->type_location, $this->getSuppressedIssues(), [], false);
}
if ($property->is_static) {
@ -1010,7 +1009,7 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
$property_type = StatementsChecker::getSimpleType($property->default) ?: Type::getMixed();
}
} else {
if ($this->getFileChecker()->project_checker->collect_references && $property_type_line_number) {
if ($property_type_line_number) {
$property_type_location = new CodeLocation($this, $stmt);
$property_type_location->setCommentLine($property_type_line_number);
}
@ -1128,13 +1127,15 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
* @param FileChecker $file_checker
* @param CodeLocation $code_location
* @param array<string> $suppressed_issues
* @param bool $inferred - whether or not the type was inferred
* @return bool|null
*/
public static function checkFullyQualifiedClassLikeName(
$fq_class_name,
FileChecker $file_checker,
CodeLocation $code_location,
array $suppressed_issues
array $suppressed_issues,
$inferred = true
) {
if (empty($fq_class_name)) {
throw new \InvalidArgumentException('$class cannot be empty');
@ -1163,7 +1164,7 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
return null;
}
if ($file_checker->project_checker->collect_references) {
if ($file_checker->project_checker->collect_references && !$inferred) {
$class_storage = ClassLikeChecker::$storage[strtolower($fq_class_name)];
if ($class_storage->referencing_locations === null) {
$class_storage->referencing_locations = [];

View File

@ -353,9 +353,9 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$substituted_type = clone $param_type;
$generic_types = [];
$substituted_type->replaceTemplateTypes($template_types, $generic_types, null);
$substituted_type->check($this->source, $function_param->location, $this->suppressed_issues);
$substituted_type->check($this->source, $function_param->location, $this->suppressed_issues, [], false);
} else {
$param_type->check($this->source, $function_param->location, $this->suppressed_issues);
$param_type->check($this->source, $function_param->location, $this->suppressed_issues, [], false);
}
if ($this->getFileChecker()->project_checker->collect_references) {
@ -366,7 +366,9 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$function_param->signature_type->check(
$this->source,
$function_param->signature_location,
$this->suppressed_issues
$this->suppressed_issues,
[],
false
);
}
}
@ -1087,7 +1089,9 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$declared_return_type->check(
$this,
$secondary_return_type_location ?: $return_type_location,
$this->getSuppressedIssues()
$this->getSuppressedIssues(),
[],
false
);
}

View File

@ -724,9 +724,11 @@ class CallChecker
if ($var_id === '$this') {
$does_class_exist = true;
} else {
$does_class_exist = ClassLikeChecker::classOrInterfaceExists(
$does_class_exist = ClassLikeChecker::checkFullyQualifiedClassLikeName(
$fq_class_name,
$statements_checker->getFileChecker()
$statements_checker->getFileChecker(),
new CodeLocation($statements_checker->getSource(), $stmt),
$statements_checker->getSuppressedIssues()
);
}
@ -1058,7 +1060,8 @@ class CallChecker
$fq_class_name,
$file_checker,
new CodeLocation($source, $stmt->class),
$statements_checker->getSuppressedIssues()
$statements_checker->getSuppressedIssues(),
false
);
}

View File

@ -182,13 +182,15 @@ abstract class Atomic
* @param CodeLocation $code_location
* @param array<string> $suppressed_issues
* @param array<string, bool> $phantom_classes
* @param bool $inferred
* @return false|null
*/
public function check(
StatementsSource $source,
CodeLocation $code_location,
array $suppressed_issues,
array $phantom_classes = []
array $phantom_classes = [],
$inferred = true
) {
if ($this->checked) {
return;
@ -200,7 +202,8 @@ abstract class Atomic
$this->value,
$source->getFileChecker(),
$code_location,
$suppressed_issues
$suppressed_issues,
$inferred
) === false
) {
return false;
@ -208,7 +211,7 @@ abstract class Atomic
if ($this instanceof Type\Atomic\TArray || $this instanceof Type\Atomic\TGenericObject) {
foreach ($this->type_params as $type_param) {
$type_param->check($source, $code_location, $suppressed_issues, $phantom_classes);
$type_param->check($source, $code_location, $suppressed_issues, $phantom_classes, $inferred);
}
}

View File

@ -342,20 +342,22 @@ class Union
* @param CodeLocation $code_location
* @param array<string> $suppressed_issues
* @param array<string, bool> $phantom_classes
* @param bool $inferred
* @return void
*/
public function check(
StatementsSource $source,
CodeLocation $code_location,
array $suppressed_issues,
array $phantom_classes = []
array $phantom_classes = [],
$inferred = true
) {
if ($this->checked) {
return;
}
foreach ($this->types as $atomic_type) {
$atomic_type->check($source, $code_location, $suppressed_issues, $phantom_classes);
$atomic_type->check($source, $code_location, $suppressed_issues, $phantom_classes, $inferred);
}
$this->checked = true;

View File

@ -1054,4 +1054,22 @@ class PropertyTypeTest extends PHPUnit_Framework_TestCase
$context = new Context();
$file_checker->visitAndAnalyzeMethods($context);
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage UndefinedClass
* @return void
*/
public function testUndefinedPropertyClass()
{
$stmts = self::$parser->parse('<?php
class A {
/** @var B */
public $foo;
}
');
$file_checker = new FileChecker('somefile.php', $this->project_checker, $stmts);
$file_checker->visitAndAnalyzeMethods();
}
}