diff --git a/src/CodeInspector/ClassMethodChecker.php b/src/CodeInspector/ClassMethodChecker.php index d2188c1c0..d060685e4 100644 --- a/src/CodeInspector/ClassMethodChecker.php +++ b/src/CodeInspector/ClassMethodChecker.php @@ -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, diff --git a/src/CodeInspector/StatementsChecker.php b/src/CodeInspector/StatementsChecker.php index 5eadce8fc..c1fb1621e 100644 --- a/src/CodeInspector/StatementsChecker.php +++ b/src/CodeInspector/StatementsChecker.php @@ -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; diff --git a/src/CodeInspector/Type/Union.php b/src/CodeInspector/Type/Union.php index 356cd06be..35125cdca 100644 --- a/src/CodeInspector/Type/Union.php +++ b/src/CodeInspector/Type/Union.php @@ -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;