/** * @param Node $node * A node to parse * * @return Context * A new or an unchanged context resulting from * parsing the node */ public function visitInstanceof(Node $node) : Context { // Make sure the class name exists $class_name = AST::classNameFromNode($this->context, $this->code_base, $node); return $this->context; }
/** * Visit a node with kind `\ast\AST_METHOD_CALL` * * @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 visitMethodCall(Node $node) : UnionType { $class_name = AST::classNameFromNode($this->context, $this->code_base, $node); if (empty($class_name)) { return new UnionType(); } $class_fqsen = FullyQualifiedClassName::fromstringInContext($class_name, $this->context); assert($this->code_base->hasClassWithFQSEN($class_fqsen), "Class {$class_fqsen} must exist"); $clazz = $this->code_base->getClassByFQSEN($class_fqsen); $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."); if (!$clazz->hasMethodWithName($this->code_base, $method_name)) { Log::err(Log::EUNDEF, "call to undeclared method {$class_fqsen}->{$method_name}()", $this->context->getFile(), $node->lineno); return new UnionType(); } $method = $clazz->getMethodByNameInContext($this->code_base, $method_name, $this->context); return $method->getUnionType(); }
/** * @param Node $node * A node to parse * * @return Context * A new or an unchanged context resulting from * parsing the node */ public function visitCatch(Node $node) : Context { // Get the name of the class // $class_name = $node->children['class']->children['name']; try { $class_name = AST::classNameFromNode($this->context, $this->code_base, $node); } catch (TypeException $exception) { $class_name = ''; } $clazz = null; // If we can't figure out the class name (which happens // from time to time), then give up if (!empty($class_name)) { if ($node->children['class']->flags & \ast\flags\NAME_FQ) { $class_fqsen = $node->children['class']; } else { $class_fqsen = FullyQualifiedClassName::fromStringInContext($class_name, $this->context); } // Check to see if the class actually exists if ($this->code_base->hasClassWithFQSEN($class_fqsen)) { $clazz = $this->code_base->getClassByFQSEN($class_fqsen); } else { Log::err(Log::EUNDEF, "reference to undeclared class {$class_fqsen}", $this->context->getFile(), $node->lineno); } } $variable_name = AST::variableName($node->children['var']); if (!empty($variable_name)) { $variable = Variable::fromNodeInContext($node->children['var'], $this->context, $this->code_base, false); if ($clazz) { $variable->setUnionType($clazz->getUnionType()); } $this->context->addScopeVariable($variable); } return $this->context; }
/** * @param Node $node * A node to parse * * @return Context * A new or an unchanged context resulting from * parsing the node */ public function visitInstanceof(Node $node) : Context { // Make sure the class name exists try { $class_name = AST::classNameFromNode($this->context, $this->code_base, $node); } catch (TypeException $exception) { // Ignore these errors } return $this->context; }