Phan\AST\UnionTypeVisitor::visitMethodCall PHP Method

visitMethodCall() public method

Visit a node with kind \ast\AST_METHOD_CALL
public visitMethodCall ( 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 visitMethodCall(Node $node) : UnionType
    {
        $method_name = $node->children['method'] ?? '';
        // Give up on any complicated nonsense where the
        // method name is a variable such as in
        // `$variable->$function_name()`.
        if ($method_name instanceof Node) {
            return new UnionType();
        }
        // Method names can some times turn up being
        // other method calls.
        assert(is_string($method_name), "Method name must be a string. Something else given.");
        try {
            $class_fqsen = null;
            foreach ($this->classListFromNode($node->children['class'] ?? $node->children['expr']) as $i => $class) {
                $class_fqsen = $class->getFQSEN();
                if (!$class->hasMethodWithName($this->code_base, $method_name)) {
                    continue;
                }
                try {
                    $method = $class->getMethodByNameInContext($this->code_base, $method_name, $this->context);
                    $union_type = $method->getUnionType();
                    // Map template types to concrete types
                    if ($union_type->hasTemplateType()) {
                        // Get the type of the object calling the property
                        $expression_type = UnionType::fromNode($this->context, $this->code_base, $node->children['expr']);
                        // Map template types to concrete types
                        $union_type = $union_type->withTemplateParameterTypeMap($expression_type->getTemplateParameterTypeMap($this->code_base));
                    }
                    // Remove any references to \static or \static[]
                    // once we're talking about the method's return
                    // type outside of its class
                    if ($union_type->hasStaticType()) {
                        $union_type = clone $union_type;
                        $union_type->removeType(\Phan\Language\Type\StaticType::instance());
                    }
                    if ($union_type->genericArrayElementTypes()->hasStaticType()) {
                        $union_type = clone $union_type;
                        // Find the static type on the list
                        $static_type = $union_type->getTypeSet()->find(function (Type $type) : bool {
                            return $type->isGenericArray() && $type->genericArrayElementType()->isStaticType();
                        });
                        // Remove it from the list
                        $union_type->removeType($static_type);
                    }
                    return $union_type;
                } catch (IssueException $exception) {
                    return new UnionType();
                }
            }
        } catch (IssueException $exception) {
            // Swallow it
        } catch (CodeBaseException $exception) {
            $this->emitIssue(Issue::UndeclaredClassMethod, $node->lineno ?? 0, $method_name, (string) $exception->getFQSEN());
        }
        return new UnionType();
    }