/**
* Visit a node with kind `\ast\AST_VAR`
*
* @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 UnionType
* The set of types that are possibly produced by the
* given node
*/
public function visitVar(Node $node) : UnionType
{
// $$var or ${...} (whose idea was that anyway?)
if ($node->children['name'] instanceof Node && ($node->children['name']->kind == \ast\AST_VAR || $node->children['name']->kind == \ast\AST_BINARY_OP)) {
return MixedType::instance()->asUnionType();
}
// This is nonsense. Give up.
if ($node->children['name'] instanceof Node) {
return new UnionType();
}
$variable_name = $node->children['name'];
if (!$this->context->getScope()->hasVariableWithName($variable_name)) {
if (!Variable::isSuperglobalVariableWithName($variable_name)) {
Log::err(Log::EVAR, "Variable \${$variable_name} is not defined", $this->context->getFile(), $node->lineno ?? 0);
}
} else {
$variable = $this->context->getScope()->getVariableWithName($variable_name);
return $variable->getUnionType();
}
return new UnionType();
}