public static function unionTypeFromClassNode(CodeBase $code_base, Context $context, $node) : UnionType
{
// For simple nodes or very complicated nodes,
// recurse
if (!$node instanceof \ast\Node || $node->kind != \ast\AST_NAME) {
return self::unionTypeFromNode($code_base, $context, $node);
}
$class_name = $node->children['name'];
if ('parent' === $class_name) {
if (!$context->isInClassScope()) {
throw new IssueException(Issue::fromType(Issue::ContextNotObject)($context->getFile(), $node->lineno ?? 0, [$class_name]));
}
$class = $context->getClassInScope($code_base);
if ($class->isTrait()) {
throw new IssueException(Issue::fromType(Issue::TraitParentReference)($context->getFile(), $node->lineno ?? 0, [(string) $context->getClassFQSEN()]));
}
if (!$class->hasParentType()) {
throw new IssueException(Issue::fromType(Issue::ParentlessClass)($context->getFile(), $node->lineno ?? 0, [(string) $context->getClassFQSEN()]));
}
$parent_class_fqsen = $class->getParentClassFQSEN();
if (!$code_base->hasClassWithFQSEN($parent_class_fqsen)) {
throw new IssueException(Issue::fromType(Issue::UndeclaredClass)($context->getFile(), $node->lineno ?? 0, [(string) $parent_class_fqsen]));
} else {
$parent_class = $code_base->getClassByFQSEN($parent_class_fqsen);
return $parent_class->getUnionType();
}
}
// We're going to convert the class reference to a type
$type = null;
// Check to see if the name is fully qualified
if (!($node->flags & \ast\flags\NAME_NOT_FQ)) {
if (0 !== strpos($class_name, '\\')) {
$class_name = '\\' . $class_name;
}
$type = Type::fromFullyQualifiedString($class_name);
} else {
$type = Type::fromStringInContext($class_name, $context);
}
return $type->asUnionType();
}