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

Add better checks for subclassed type comparison

This commit is contained in:
Matthew Brown 2016-07-24 23:40:23 -04:00
parent ef1d662882
commit bd90dd7ee9
3 changed files with 30 additions and 12 deletions

View File

@ -152,7 +152,8 @@ class ClassMethodChecker extends FunctionChecker
}
foreach ($simple_declared_types as $simple_declared_type) {
if (is_subclass_of($differing_type, $simple_declared_type) ||
if (($simple_declared_type === 'object' && ClassChecker::classExists($differing_type)) ||
ClassChecker::classExtendsOrImplements($differing_type, $simple_declared_type) ||
(in_array($differing_type, ['float', 'double', 'int']) && in_array($simple_declared_type, ['float', 'double', 'int'])) ||
(in_array($differing_type, ['boolean', 'bool']) && in_array($simple_declared_type, ['boolean', 'bool']))
) {
@ -715,11 +716,11 @@ class ClassMethodChecker extends FunctionChecker
}
}
if (is_subclass_of($method_class, $calling_context) && method_exists($calling_context, $method_name)) {
if (ClassChecker::classExtends($method_class, $calling_context) && method_exists($calling_context, $method_name)) {
return;
}
if (!is_subclass_of($calling_context, $method_class)) {
if (!ClassChecker::classExtends($calling_context, $method_class)) {
if (IssueBuffer::accepts(
new InaccessibleMethod(
'Cannot access protected method ' . $method_id . ' from context ' . $calling_context,

View File

@ -757,7 +757,7 @@ class StatementsChecker
$use_context = new Context();
if (!$this->_is_static) {
$this_class = ClassChecker::getThisClass() && is_subclass_of(ClassChecker::getThisClass(), $this->_absolute_class) ?
$this_class = ClassChecker::getThisClass() && ClassChecker::classExtends(ClassChecker::getThisClass(), $this->_absolute_class) ?
ClassChecker::getThisClass() :
$this->_absolute_class;
@ -1851,7 +1851,7 @@ class StatementsChecker
if (ClassChecker::getThisClass() &&
(
ClassChecker::getThisClass() === $this->_absolute_class ||
is_subclass_of(ClassChecker::getThisClass(), $this->_absolute_class) ||
ClassChecker::classExtends(ClassChecker::getThisClass(), $this->_absolute_class) ||
trait_exists($this->_absolute_class)
)) {
@ -1945,7 +1945,7 @@ class StatementsChecker
if (!($this->_source->getSource() instanceof TraitChecker)) {
$calling_context = $this->_absolute_class;
if (ClassChecker::getThisClass() && is_subclass_of(ClassChecker::getThisClass(), $this->_absolute_class)) {
if (ClassChecker::getThisClass() && ClassChecker::classExtends(ClassChecker::getThisClass(), $this->_absolute_class)) {
$calling_context = $this->_absolute_class;
}
@ -2752,7 +2752,7 @@ class StatementsChecker
}
if ($input_type_part->value === $param_type_part->value ||
is_subclass_of($input_type_part->value, $param_type_part->value) ||
ClassChecker::classExtends($input_type_part->value, $param_type_part->value) ||
self::isMock($input_type_part->value)
) {
$type_match_found = true;
@ -2786,7 +2786,7 @@ class StatementsChecker
}
if (is_subclass_of($param_type_part->value, $input_type_part->value)) {
if (ClassChecker::classExtends($param_type_part->value, $input_type_part->value)) {
// @todo handle coercion
$type_match_found = true;
break;

View File

@ -3,6 +3,7 @@
namespace CodeInspector\Type;
use CodeInspector\Type;
use CodeInspector\ClassChecker;
class Union extends Type
{
@ -79,7 +80,7 @@ class Union extends Type
public function isIn(Union $parent)
{
foreach ($this->types as $type) {
if (strtoupper($type->value[0]) === $type->value[0] && $parent->hasType('object')) {
if ($parent->hasType('object') && ClassChecker::classExists($type->value)) {
continue;
}
@ -88,11 +89,27 @@ class Union extends Type
continue;
}
if (!$parent->hasType($type->value)) {
return false;
if ($parent->hasType($type->value)) {
continue;
}
// @todo add is_subclass_of
// last check to see if class is subclass
if (ClassChecker::classExists($type->value)) {
$type_is_subclass = false;
foreach ($parent->types as $parent_type) {
if (ClassChecker::classExtendsOrImplements($type->value, $parent_type->value)) {
$type_is_subclass = true;
break;
}
}
if ($type_is_subclass) {
continue;
}
}
return false;
}
return true;