public function visitMethod(Decl $node) : Context
{
$method_name = (string) $node->name;
assert($this->context->isInClassScope(), "Must be in class context to see a method");
$clazz = $this->getContextClass();
if (!$clazz->hasMethodWithName($this->code_base, $method_name)) {
throw new CodeBaseException(null, "Can't find method {$clazz->getFQSEN()}::{$method_name}() - aborting");
}
$method = $clazz->getMethodByNameInContext($this->code_base, $method_name, $this->context);
// Parse the comment above the method to get
// extra meta information about the method.
$comment = Comment::fromStringInContext($node->docComment ?? '', $this->context);
$context = $this->context->withScope($method->getInternalScope());
// For any @var references in the method declaration,
// add them as variables to the method's scope
foreach ($comment->getVariableList() as $parameter) {
$context->addScopeVariable($parameter->asVariable($this->context));
}
// Add $this to the scope of non-static methods
if (!($node->flags & \ast\flags\MODIFIER_STATIC)) {
assert($clazz->getInternalScope()->hasVariableWithName('this'), "Classes must have a \$this variable.");
$context->addScopeVariable($clazz->getInternalScope()->getVariableByName('this'));
}
// Add each method parameter to the scope. We clone it
// so that changes to the variable don't alter the
// parameter definition
foreach ($method->getParameterList() as $parameter) {
$context->addScopeVariable(clone $parameter);
}
if ($this->analyzeFunctionLikeIsGenerator($node)) {
$this->setReturnTypeOfGenerator($method, $node);
}
return $context;
}