/**
  * Create from a Class Node
  *
  * @param ClassNode $node
  * @param LocatedSource $locatedSource
  * @param NamespaceNode|null $namespace optional - if omitted, we assume it is global namespaced class
  * @return ReflectionClass
  */
 public static function createFromNode(ClassNode $node, LocatedSource $locatedSource, NamespaceNode $namespace = null)
 {
     $class = new self();
     $class->locatedSource = $locatedSource;
     $class->name = $node->name;
     if (null !== $namespace) {
         $class->declaringNamespace = $namespace;
     }
     $methodNodes = $node->getMethods();
     foreach ($methodNodes as $methodNode) {
         $class->methods[] = ReflectionMethod::createFromNode($methodNode, $class);
     }
     foreach ($node->stmts as $stmt) {
         if ($stmt instanceof ConstNode) {
             $constName = $stmt->consts[0]->name;
             $constValue = (new CompileNodeToValue())->__invoke($stmt->consts[0]->value);
             $class->constants[$constName] = $constValue;
         }
         if ($stmt instanceof PropertyNode) {
             $prop = ReflectionProperty::createFromNode($stmt, $class);
             $class->properties[$prop->getName()] = $prop;
         }
     }
     return $class;
 }
 /**
  * Get only the methods that this class implements (i.e. do not search
  * up parent classes etc.)
  *
  * @return ReflectionMethod[]
  */
 public function getImmediateMethods()
 {
     /* @var $methods \ReflectionMethod[] */
     $methods = array_map(function (ClassMethod $methodNode) {
         return ReflectionMethod::createFromNode($this->reflector, $methodNode, $this);
     }, $this->node->getMethods());
     $methodsByName = [];
     foreach ($methods as $method) {
         $methodsByName[$method->getName()] = $method;
     }
     return $methodsByName;
 }
 /**
  * Create from a Class Node.
  *
  * @param Reflector          $reflector
  * @param ClassLikeNode      $node
  * @param LocatedSource      $locatedSource
  * @param NamespaceNode|null $namespace optional - if omitted, we assume it is global namespaced class
  *
  * @return ReflectionClass
  */
 public static function createFromNode(Reflector $reflector, ClassLikeNode $node, LocatedSource $locatedSource, NamespaceNode $namespace = null)
 {
     $class = new self();
     $class->reflector = $reflector;
     $class->node = $node;
     $class->locatedSource = $locatedSource;
     $class->name = $node->name;
     if (null !== $namespace) {
         $class->declaringNamespace = $namespace;
     }
     if ($node instanceof ClassNode && null !== $node->extends) {
         $objectType = (new FindTypeFromAst())->__invoke($node->extends, $locatedSource, $class->getNamespaceName());
         if (null !== $objectType && $objectType instanceof Object_) {
             $class->extendsClassType = $objectType->getFqsen();
         }
     }
     $methodNodes = $node->getMethods();
     foreach ($methodNodes as $methodNode) {
         $class->methods[] = ReflectionMethod::createFromNode($methodNode, $class);
     }
     foreach ($node->stmts as $stmt) {
         if ($stmt instanceof ConstNode) {
             $constName = $stmt->consts[0]->name;
             $constValue = (new CompileNodeToValue())->__invoke($stmt->consts[0]->value);
             $class->constants[$constName] = $constValue;
         }
         if ($stmt instanceof PropertyNode) {
             $prop = ReflectionProperty::createFromNode($stmt, $class);
             $class->properties[$prop->getName()] = $prop;
         }
     }
     return $class;
 }
 /**
  * Construct a flat list of methods that are available. This will search up
  * all parent classes/traits/interfaces/current scope for methods.
  *
  * @return ReflectionMethod[]
  */
 private function scanMethods()
 {
     // merging together methods from interfaces, parent class, traits, current class (in this precise order)
     /* @var $inheritedMethods \ReflectionMethod[] */
     $inheritedMethods = array_merge(array_merge([], ...array_map(function (ReflectionClass $ancestor) {
         return $ancestor->getMethods();
     }, array_values(array_merge($this->getInterfaces(), array_filter([$this->getParentClass()]), $this->getTraits())))), array_map(function (ClassMethod $methodNode) {
         return ReflectionMethod::createFromNode($this->reflector, $methodNode, $this);
     }, $this->node->getMethods()));
     $methodsByName = [];
     foreach ($inheritedMethods as $inheritedMethod) {
         $methodsByName[$inheritedMethod->getName()] = $inheritedMethod;
     }
     return $methodsByName;
 }