/** * 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; }