/** * @param Node $node * A node to parse * * @return Context * A new or an unchanged context resulting from * parsing the node */ public function visitVar(Node $node) : Context { $variable_name = (new ContextNode($this->code_base, $this->context, $node))->getVariableName(); // Check to see if the variable already exists if ($this->context->getScope()->hasVariableWithName($variable_name)) { $variable = $this->context->getScope()->getVariableWithName($variable_name); // If we're assigning to an array element then we don't // know what the constitutation of the parameter is // outside of the scope of this assignment, so we add to // its union type rather than replace it. if ($this->is_dim_assignment) { $variable->getUnionType()->addUnionType($this->right_type); } else { // If the variable isn't a pass-by-reference paramter // we clone it so as to not disturb its previous types // as we replace it. if ($variable instanceof Parameter) { if ($variable->isPassByReference()) { } else { $variable = clone $variable; } } else { $variable = clone $variable; } if ($this->context->getIsConditional()) { // If we're within a conditional, we shouldn't // replace the type since the other side of // the branch may have another type $variable->getUnionType()->addUnionType($this->right_type); } else { $variable->setUnionType($this->right_type); } } $this->context->addScopeVariable($variable); return $this->context; } $variable = Variable::fromNodeInContext($this->assignment_node, $this->context, $this->code_base); // Set that type on the variable $variable->getUnionType()->addUnionType($this->right_type); // Note that we're not creating a new scope, just // adding variables to the existing scope $this->context->addScopeVariable($variable); return $this->context; }