Phan\AST\UnionTypeVisitor::unionTypeFromClassNode PHP Method

unionTypeFromClassNode() public static method

public static unionTypeFromClassNode ( CodeBase $code_base, Context $context, ast\Node | mixed $node ) : UnionType
$code_base Phan\CodeBase The code base within which we're operating
$context Phan\Language\Context $context The context of the parser at the node for which we'd like to determine a type
$node ast\Node | mixed The node for which we'd like to determine its type
return Phan\Language\UnionType The UnionType associated with the given node in the given Context within the given CodeBase
    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();
    }

Usage Example

Beispiel #1
0
 /**
  * @param Node $node
  * A node of the type indicated by the method name that we'd
  * like to figure out the type that it produces.
  *
  * @return string
  * The class name represented by the given call
  */
 public function visitNew(Node $node) : string
 {
     // Things of the form `new $class_name();`
     if ($node->children['class']->kind == \ast\AST_VAR) {
         return '';
     }
     // Anonymous class
     // $v = new class { ... }
     if ($node->children['class']->kind == \ast\AST_CLASS && $node->children['class']->flags & \ast\flags\CLASS_ANONYMOUS) {
         return AST::unqualifiedNameForAnonymousClassNode($node->children['class'], $this->context);
     }
     // Things of the form `new $method->name()`
     if ($node->children['class']->kind !== \ast\AST_NAME) {
         return '';
     }
     $class_name = $node->children['class']->children['name'];
     if (!in_array($class_name, ['self', 'static', 'parent'])) {
         return (string) UnionTypeVisitor::unionTypeFromClassNode($this->code_base, $this->context, $node->children['class']);
     }
     if (!$this->context->isInClassScope()) {
         Log::err(Log::ESTATIC, "Cannot access {$class_name}:: when no class scope is active", $this->context->getFile(), $node->lineno);
         return '';
     }
     if ($class_name == 'static') {
         return (string) $this->context->getClassFQSEN();
     }
     if ($class_name == 'self') {
         if ($this->context->isGlobalScope()) {
             assert(false, "Unimplemented branch is required for {$this->context}");
         } else {
             return (string) $this->context->getClassFQSEN();
         }
     }
     if ($class_name == 'parent') {
         $clazz = $this->context->getClassInScope($this->code_base);
         if (!$clazz->hasParentClassFQSEN()) {
             return '';
         }
         return (string) $clazz->getParentClassFQSEN();
     }
     return '';
 }
All Usage Examples Of Phan\AST\UnionTypeVisitor::unionTypeFromClassNode