Phan\BlockAnalysisVisitor::visitBranchedContext PHP Method

visitBranchedContext() public method

│ ▼ ┌──●──┐ │ │ │ ● ● ● │ │ │ └──●──┘ │ ▼
public visitBranchedContext ( ast\Node $node ) : Context
$node ast\Node An AST node we'd like to determine the UnionType for
return Phan\Language\Context The updated context after visiting the node
    public function visitBranchedContext(Node $node) : Context
    {
        $context = $this->context->withLineNumberStart($node->lineno ?? 0);
        // Visit the given node populating the code base
        // with anything we learn and get a new context
        // indicating the state of the world within the
        // given node
        $context = (new PreOrderAnalysisVisitor($this->code_base, $context))($node);
        assert(!empty($context), 'Context cannot be null');
        // We collect all child context so that the
        // PostOrderAnalysisVisitor can optionally operate on
        // them
        $child_context_list = [];
        // With a context that is inside of the node passed
        // to this method, we analyze all children of the
        // node.
        foreach ($node->children ?? [] as $node_key => $child_node) {
            // Skip any non Node children.
            if (!$child_node instanceof Node) {
                continue;
            }
            if (!Analysis::shouldVisit($child_node)) {
                continue;
            }
            // The conditions need to communicate to the outter
            // scope for things like assigning veriables.
            if ($child_node->kind != \ast\AST_IF_ELEM) {
                $child_context = $context->withScope(new BranchScope($context->getScope()));
            } else {
                $child_context = $context;
            }
            $child_context->withLineNumberStart($child_node->lineno ?? 0);
            // Step into each child node and get an
            // updated context for the node
            $child_context = (new BlockAnalysisVisitor($this->code_base, $child_context, $node, $this->depth + 1))($child_node);
            $child_context_list[] = $child_context;
        }
        // For if statements, we need to merge the contexts
        // of all child context into a single scope based
        // on any possible branching structure
        $context = (new ContextMergeVisitor($this->code_base, $context, $child_context_list))($node);
        // Now that we know all about our context (like what
        // 'self' means), we can analyze statements like
        // assignments and method calls.
        $context = (new PostOrderAnalysisVisitor($this->code_base, $context->withLineNumberStart($node->lineno ?? 0), $this->parent_node))($node);
        // When coming out of a scoped element, we pop the
        // context to be the incoming context. Otherwise,
        // we pass our new context up to our parent
        return $context;
    }