public function visitIfElem(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');
$condition_node = $node->children['cond'];
if ($condition_node && $condition_node instanceof Node) {
$context = (new BlockAnalysisVisitor($this->code_base, $context->withLineNumberStart($condition_node->lineno ?? 0), $node, $this->depth + 1))($condition_node);
}
if ($stmts_node = $node->children['stmts']) {
if ($stmts_node instanceof Node) {
$context = (new BlockAnalysisVisitor($this->code_base, $context->withScope(new BranchScope($context->getScope()))->withLineNumberStart($stmts_node->lineno ?? 0), $node, $this->depth + 1))($stmts_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;
}