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:
parent
ef1d662882
commit
bd90dd7ee9
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user