Phan\AST\UnionTypeVisitor::visitNew PHP Method

visitNew() public method

Visit a node with kind \ast\AST_NEW
public visitNew ( ast\Node $node ) : UnionType
$node ast\Node A node of the type indicated by the method name that we'd like to figure out the type that it produces.
return Phan\Language\UnionType The set of types that are possibly produced by the given node
    public function visitNew(Node $node) : UnionType
    {
        $union_type = $this->visitClassNode($node->children['class']);
        // For any types that are templates, map them to concrete
        // types based on the parameters passed in.
        return new UnionType(array_map(function (Type $type) use($node) {
            // Get a fully qualified name for the type
            $fqsen = $type->asFQSEN();
            // If this isn't a class, its fine as is
            if (!$fqsen instanceof FullyQualifiedClassName) {
                return $type;
            }
            assert($fqsen instanceof FullyQualifiedClassName);
            // If we don't have the class, we'll catch that problem
            // elsewhere
            if (!$this->code_base->hasClassWithFQSEN($fqsen)) {
                return $type;
            }
            $class = $this->code_base->getClassByFQSEN($fqsen);
            // If this class doesn't have any generics on it, we're
            // fine as we are with this Type
            if (!$class->isGeneric()) {
                return $type;
            }
            // Now things are interesting. We need to map the
            // arguments to the generic types and return a special
            // kind of type.
            // Get the constructor so that we can figure out what
            // template types we're going to be mapping
            $constructor_method = $class->getMethodByName($this->code_base, '__construct');
            // Map each argument to its type
            $arg_type_list = array_map(function ($arg_node) {
                return UnionType::fromNode($this->context, $this->code_base, $arg_node);
            }, $node->children['args']->children ?? []);
            // Map each template type o the argument's concrete type
            $template_type_list = [];
            foreach ($constructor_method->getParameterList() as $i => $parameter) {
                if (isset($arg_type_list[$i])) {
                    $template_type_list[] = $arg_type_list[$i];
                }
            }
            // Create a new type that assigns concrete
            // types to template type identifiers.
            return Type::fromType($type, $template_type_list);
        }, $union_type->getTypeSet()->toArray()));
    }