Parses interfaces from the concrete class node

@param ClassLike $classLikeNode Class-like node

@return array|\ReflectionClass[] List of reflections of interfaces
487479
public static function collectInterfacesFromClassNode(ClassLike $classLikeNode)
    {
        $interfaces = [];

        $isInterface    = $classLikeNode instanceof Interface_;
        $interfaceField = $isInterface ? 'extends' : 'implements';
        $hasInterfaces  = in_array($interfaceField, $classLikeNode->getSubNodeNames());
        $implementsList = $hasInterfaces ? $classLikeNode->$interfaceField : array();
        if ($implementsList) {
            foreach ($implementsList as $implementNode) {
                if ($implementNode instanceof FullyQualified) {
                    $implementName  = $implementNode->toString();
                    $interface      = interface_exists($implementName, false)
                        ? new parent($implementName)
                        : new static($implementName);
                    $interfaces[$implementName] = $interface;
                }
            }
        }

        return $interfaces;
    }
1269789
public function getNodes(?callable $filter = null, string $namespace = self::DEFAULT_NAMESPACE): array
    {
        $nodes = [];
        $nodeRefs = $this->nodeRefs[$namespace] ?? [];

        foreach ($nodeRefs as $key => $nodeRef) {
            try {
                $node = $this->ncrCache->getNode($nodeRef);
                if (null === $filter || $filter($node, $nodeRef)) {
                    $nodes[$key] = $node;
                }
            } catch (\Throwable $e) {
                // if you don't node me by now, you will never never never node me.
            }
        }

        return $nodes;
    }
1141304
public static function extractClassLikeDocblockInfo(\PhpParser\Node $node, $comment, $line_number)
    {
        $comments = DocComment::parse($comment, $line_number);

        $info = new ClassLikeDocblockComment();

        if (isset($comments['specials']['template']) || isset($comments['specials']['psalm-template'])) {
            $all_templates = (isset($comments['specials']['template']) ? $comments['specials']['template'] : [])
                + (isset($comments['specials']['psalm-template']) ? $comments['specials']['psalm-template'] : []);

            foreach ($all_templates as $template_line) {
                $template_type = preg_split('/[\s]+/', $template_line);

                $template_name = array_shift($template_type);

                if (count($template_type) > 1
                    && in_array(strtolower($template_type[0]), ['as', 'super', 'of'], true)
                ) {
                    $template_modifier = strtolower(array_shift($template_type));
                    $info->templates[] = [
                        $template_name,
                        $template_modifier,
                        implode(' ', $template_type)
                    ];
                } else {
                    $info->templates[] = [$template_name];
                }
            }
        }

        if (isset($comments['specials']['template-extends'])
            || isset($comments['specials']['inherits'])
            || isset($comments['specials']['extends'])
        ) {
            $all_inheritance = array_merge(
                $comments['specials']['template-extends'] ?? [],
                $comments['specials']['inherits'] ?? [],
                $comments['specials']['extends'] ?? []
            );

            foreach ($all_inheritance as $template_line) {
                $info->template_extends[] = $template_line;
            }
        }

        if (isset($comments['specials']['template-implements'])
            || isset($comments['specials']['implements'])
        ) {
            $all_inheritance = array_merge(
                $comments['specials']['template-implements'] ?? [],
                $comments['specials']['implements'] ?? []
            );

            foreach ($all_inheritance as $template_line) {
                $info->template_implements[] = $template_line;
            }
        }

        if (isset($comments['specials']['deprecated'])) {
            $info->deprecated = true;
        }

        if (isset($comments['specials']['internal'])) {
            $info->internal = true;
        }

        if (isset($comments['specials']['psalm-seal-properties'])) {
            $info->sealed_properties = true;
        }

        if (isset($comments['specials']['psalm-seal-methods'])) {
            $info->sealed_methods = true;
        }

        if (isset($comments['specials']['psalm-override-property-visibility'])) {
            $info->override_property_visibility = true;
        }

        if (isset($comments['specials']['psalm-override-method-visibility'])) {
            $info->override_method_visibility = true;
        }

        if (isset($comments['specials']['psalm-suppress'])) {
            foreach ($comments['specials']['psalm-suppress'] as $suppress_entry) {
                $info->suppressed_issues[] = preg_split('/[\s]+/', $suppress_entry)[0];
            }
        }

        if (isset($comments['specials']['method']) || isset($comments['specials']['psalm-method'])) {
            $all_methods = (isset($comments['specials']['method']) ? $comments['specials']['method'] : [])
                + (isset($comments['specials']['psalm-method']) ? $comments['specials']['psalm-method'] : []);

            foreach ($all_methods as $line_number => $method_entry) {
                $method_entry = preg_replace('/[ \t]+/', ' ', trim($method_entry));

                $docblock_lines = [];

                $is_static = false;

                if (!preg_match('/^([a-z_A-Z][a-z_0-9A-Z]+) *\(/', $method_entry, $matches)) {
                    $doc_line_parts = self::splitDocLine($method_entry);

                    if ($doc_line_parts[0] === 'static' && !strpos($doc_line_parts[1], '(')) {
                        $is_static = true;
                        array_shift($doc_line_parts);
                    }

                    $docblock_lines[] = '@return ' . array_shift($doc_line_parts);

                    $method_entry = implode(' ', $doc_line_parts);
                }

                $method_entry = trim(preg_replace('/\/\/.*/', '', $method_entry));

                $end_of_method_regex = '/(?<!array\()\) ?(\: ?(\??[\\\\a-zA-Z0-9_]+))?/';

                if (preg_match($end_of_method_regex, $method_entry, $matches, PREG_OFFSET_CAPTURE)) {
                    $method_entry = substr($method_entry, 0, (int) $matches[0][1] + strlen((string) $matches[0][0]));
                }

                $method_entry = str_replace([', ', '( '], [',', '('], $method_entry);
                $method_entry = preg_replace('/ (?!(\$|\.\.\.|&))/', '', trim($method_entry));

                try {
                    $method_tree = ParseTree::createFromTokens(Type::tokenize($method_entry, false));
                } catch (TypeParseTreeException $e) {
                    throw new DocblockParseException($method_entry . ' is not a valid method');
                }

                if (!$method_tree instanceof ParseTree\MethodWithReturnTypeTree
                    && !$method_tree instanceof ParseTree\MethodTree) {
                    throw new DocblockParseException($method_entry . ' is not a valid method');
                }

                if ($method_tree instanceof ParseTree\MethodWithReturnTypeTree) {
                    $docblock_lines[] = '@return ' . Type::getTypeFromTree($method_tree->children[1]);
                    $method_tree = $method_tree->children[0];
                }

                if (!$method_tree instanceof ParseTree\MethodTree) {
                    throw new DocblockParseException($method_entry . ' is not a valid method');
                }

                $args = [];

                foreach ($method_tree->children as $method_tree_child) {
                    if (!$method_tree_child instanceof ParseTree\MethodParamTree) {
                        throw new DocblockParseException($method_entry . ' is not a valid method');
                    }

                    $args[] = ($method_tree_child->byref ? '&' : '')
                        . ($method_tree_child->variadic ? '...' : '')
                        . $method_tree_child->name
                        . ($method_tree_child->default != '' ? ' = ' . $method_tree_child->default : '');


                    if ($method_tree_child->children) {
                        $param_type = Type::getTypeFromTree($method_tree_child->children[0]);
                        $docblock_lines[] = '@param ' . $param_type . ' '
                            . ($method_tree_child->variadic ? '...' : '')
                            . $method_tree_child->name;
                    }
                }

                $function_string = 'function ' . $method_tree->value . '(' . implode(', ', $args) . ')';

                if ($is_static) {
                    $function_string = 'static ' . $function_string;
                }

                $function_docblock = $docblock_lines ? "/**\n * " . implode("\n * ", $docblock_lines) . "\n*/\n" : "";

                $php_string = '<?php class A { ' . $function_docblock . ' public ' . $function_string . '{} }';

                try {
                    $statements = \Psalm\Internal\Provider\StatementsProvider::parseStatements($php_string);
                } catch (\Exception $e) {
                    throw new DocblockParseException('Badly-formatted @method string ' . $method_entry);
                }

                if (!$statements[0] instanceof \PhpParser\Node\Stmt\Class_
                    || !isset($statements[0]->stmts[0])
                    || !$statements[0]->stmts[0] instanceof \PhpParser\Node\Stmt\ClassMethod
                ) {
                    throw new DocblockParseException('Badly-formatted @method string ' . $method_entry);
                }

                /** @var \PhpParser\Comment\Doc */
                $node_doc_comment = $node->getDocComment();

                $statements[0]->stmts[0]->setAttribute('startLine', $node_doc_comment->getLine());
                $statements[0]->stmts[0]->setAttribute('startFilePos', $node_doc_comment->getFilePos());
                $statements[0]->stmts[0]->setAttribute('endFilePos', $node->getAttribute('startFilePos'));

                if ($doc_comment = $statements[0]->stmts[0]->getDocComment()) {
                    $statements[0]->stmts[0]->setDocComment(
                        new \PhpParser\Comment\Doc(
                            $doc_comment->getText(),
                            $line_number,
                            $node_doc_comment->getFilePos()
                        )
                    );
                }

                $info->methods[] = $statements[0]->stmts[0];
            }
        }

        self::addMagicPropertyToInfo($info, $comments['specials'], 'property');
        self::addMagicPropertyToInfo($info, $comments['specials'], 'psalm-property');
        self::addMagicPropertyToInfo($info, $comments['specials'], 'property-read');
        self::addMagicPropertyToInfo($info, $comments['specials'], 'property-write');

        return $info;
    }
901187
public function getClassAnnotations($className, $annotationClassName = null)
    {
        $className = $this->prepareClassReflectionForUsage($className);

        $annotationClassName = $annotationClassName === null ? null : $this->cleanClassName($annotationClassName);
        if (!isset($this->classReflectionData[$className][self::DATA_CLASS_ANNOTATIONS])) {
            return [];
        }
        if ($annotationClassName === null) {
            return $this->classReflectionData[$className][self::DATA_CLASS_ANNOTATIONS];
        }

        $annotations = [];
        foreach ($this->classReflectionData[$className][self::DATA_CLASS_ANNOTATIONS] as $annotation) {
            if ($annotation instanceof $annotationClassName) {
                $annotations[] = $annotation;
            }
        }

        return $annotations;
    }
1181613
private function classLineage($class, $ident = null)
    {
        if (!is_string($class)) {
            return [];
        }

        if ($ident === null) {
            $ident = $this->metaKeyFromClassName($class);
        }

        if (isset(static::$lineageCache[$ident])) {
            return static::$lineageCache[$ident];
        }

        $class = $this->classNameFromMetaKey($ident);

        if (!class_exists($class) && !interface_exists($class)) {
            return [ $ident ];
        }

        $classes   = array_values(class_parents($class));
        $classes   = array_reverse($classes);
        $classes[] = $class;

        $hierarchy = [];
        foreach ($classes as $class) {
            $implements = array_values(class_implements($class));
            $implements = array_reverse($implements);
            foreach ($implements as $interface) {
                $hierarchy[$this->metaKeyFromClassName($interface)] = 1;
            }
            $hierarchy[$this->metaKeyFromClassName($class)] = 1;
        }

        $hierarchy = array_keys($hierarchy);

        static::$lineageCache[$ident] = $hierarchy;

        return $hierarchy;
    }
31805
public function getInstanceNodes(TreeNodeInterface $node)
    {
        $instanceNodes = [];
        foreach ($this->getAll() as $tree) {
            $instanceNodes = array_merge($instanceNodes, $tree->getInstances($node));
        }

        return $instanceNodes;
    }
23287
function classGetReflection($class) {
    if (array_key_exists($class, $this->classLikesByQcn)) {
      return $this->classLikesByQcn[$class];
    }
    if (class_exists($class, FALSE) || interface_exists($class, FALSE) || trait_exists($class, FALSE)) {
      $reflectionClass = new \ReflectionClass($class);
      $this->initKnownClass($class, $reflectionClass);
    }
    else {
      $this->triggerAutoload($class);
    }
    if (isset($this->classLikesByQcn[$class])) {
      return $this->classLikesByQcn[$class];
    }
    if (array_key_exists($class, $this->classLikesByQcn)) {
      return $this->classLikesByQcn[$class];
    }
    return NULL;
  }
148117
public static function collectTraitsFromClassNode(ClassLike $classLikeNode, array &$traitAdaptations)
    {
        $traits = [];

        if (!empty($classLikeNode->stmts)) {
            foreach ($classLikeNode->stmts as $classLevelNode) {
                if ($classLevelNode instanceof TraitUse) {
                    foreach ($classLevelNode->traits as $classTraitName) {
                        if ($classTraitName instanceof FullyQualified) {
                            $traitName          = $classTraitName->toString();
                            $trait              = trait_exists($traitName, false)
                                ? new parent($traitName)
                                : new static($traitName);
                            $traits[$traitName] = $trait;
                        }
                    }
                    $traitAdaptations = $classLevelNode->adaptations;
                }
            }
        }

        return $traits;
    }
892330
protected function parseMethods(SimpleXMLElement $class)
    {
        $methods = [];

        $className = (string)$class->full_name;
        $className = ltrim($className, '\\');

        foreach ($class->method as $method) {
            $methodName = (string)$method->name;

            $return = $method->xpath('docblock/tag[@name="return"]');

            if (count($return)) {
                $return = (string)$return[0]['type'];
            } else {
                $return = 'mixed';
            }

            $arguments = [];

            foreach ($method->argument as $argument) {
                $nArgument = [
                    'type' => (string)$argument->type,
                    'name' => (string)$argument->name
                ];

                $tags = $method->xpath(
                    sprintf('docblock/tag[@name="param" and @variable="%s"]', $nArgument['name'])
                );

                if (count($tags)) {
                    $tag = $tags[0];

                    if ((string)$tag['type']) {
                        $nArgument['type'] = (string)$tag['type'];
                    }

                    if ((string)$tag['description']) {
                        $nArgument['description'] = (string)$tag['description'];
                    }

                    if ((string)$tag['variable']) {
                        $nArgument['name'] = (string)$tag['variable'];
                    }
                }

                $arguments[] = $nArgument;
            }

            $argumentStr = implode(', ', array_map(function($argument) {
                $return = $argument['name'];

                if ($argument['type']) {
                    $return = $argument['type'] . ' ' . $return;
                }

                return $return;
            }, $arguments));

            $signature = sprintf('%s %s::%s(%s)', $return, $className, $methodName, $argumentStr);

            $methods[$methodName] = [
                'name'        => $methodName,
                'description' => (string)$method->docblock->description . "\n\n" . (string)$method->docblock->{'long-description'},
                'visibility'  => (string)$method['visibility'],
                'abstract'    => ((string)$method['abstract']) == "true",
                'static'      => ((string)$method['static']) == "true",
                'deprecated'  => count($class->xpath('docblock/tag[@name="deprecated"]')) > 0,
                'signature'   => $signature,
                'arguments'   => $arguments,
                'definedBy'   => $className,
            ];
        }

        return $methods;
    }
587260
public function getInterfaceNames()
    {
        $interfaces = array();

        if ($this->node instanceof Node\Stmt\Class_) {
            foreach ($this->node->implements as $interface) {
                $interfaces[] = (string) $interface;
            }
        }

        return $interfaces;
    }
750192
protected function collectEditingClassNames(NodeInterface $node)
    {
        $classNames = [];

        if ($node->getNodeType()->isOfType('Neos.Neos:ContentCollection')) {
            // This is needed since the backend relies on this class (should not be necessary)
            $classNames[] = 'neos-contentcollection';
        } else {
            $classNames[] = 'neos-contentelement';
        }

        if ($node->isRemoved()) {
            $classNames[] = 'neos-contentelement-removed';
        }

        if ($node->isHidden()) {
            $classNames[] = 'neos-contentelement-hidden';
        }

        if ($this->isInlineEditable($node) === false) {
            $classNames[] = 'neos-not-inline-editable';
        }

        return $classNames;
    }
418018
protected function getRoutableNodeClasses()
    {
        $metadata = $this->manager->getClassMetadata(Node::class);
        $routables = array_values(array_filter($metadata->subClasses, function($subNode) {
            $reflection = new \ReflectionClass($subNode);
            return $reflection->implementsInterface(RoutableNodeInterface::class);
        }));

        return $routables;
    }
748683
public function getNodeTypeNamesDeniedForCreation(NodeInterface $referenceNode)
    {
        $privilegeSubject = new CreateNodePrivilegeSubject($referenceNode);

        $allNodeTypes = $this->nodeTypeManager->getNodeTypes();

        $deniedCreationNodeTypes = [];
        $grantedCreationNodeTypes = [];
        $abstainedCreationNodeTypes = [];
        foreach ($this->securityContext->getRoles() as $role) {
            /** @var CreateNodePrivilege $createNodePrivilege */
            foreach ($role->getPrivilegesByType(CreateNodePrivilege::class) as $createNodePrivilege) {
                if (!$createNodePrivilege->matchesSubject($privilegeSubject)) {
                    continue;
                }

                $affectedNodeTypes = ($createNodePrivilege->getCreationNodeTypes() !== [] ? $createNodePrivilege->getCreationNodeTypes() : $allNodeTypes);

                if ($createNodePrivilege->isGranted()) {
                    $grantedCreationNodeTypes = array_merge($grantedCreationNodeTypes, $affectedNodeTypes);
                } elseif ($createNodePrivilege->isDenied()) {
                    $deniedCreationNodeTypes = array_merge($deniedCreationNodeTypes, $affectedNodeTypes);
                } else {
                    $abstainedCreationNodeTypes = array_merge($abstainedCreationNodeTypes, $affectedNodeTypes);
                }
            }
        }
        $implicitlyDeniedNodeTypes = array_diff($abstainedCreationNodeTypes, $grantedCreationNodeTypes);
        return array_merge($implicitlyDeniedNodeTypes, $deniedCreationNodeTypes);
    }
287750
public function parseClass(\ReflectionClass $class)
    {
        if (false === $filename = $class->getFilename()) {
            return array();
        }

        $content = $this->getFileContent($filename, $class->getStartLine());
        $namespace = str_replace('\\', '\\\\', $class->getNamespaceName());
        $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
        $this->tokens = token_get_all('<?php ' . $content);
        $this->numTokens = count($this->tokens);
        $this->pointer = 0;

        $statements = $this->parseUseStatements($class->getNamespaceName());

        return $statements;
    }
888280
private function getFromAnnotation(ReflectionClass $class): array
    {
        $sortings = Utils::getRecursiveClassAnnotations($this->getAnnotationReader(), $class, Sorting::class);

        $result = [];
        foreach ($sortings as $classWithAnnotation => $sorting) {
            foreach ($sorting->classes as $className) {
                $this->throwIfInvalidAnnotation($classWithAnnotation, 'Sorting', SortingInterface::class, $className);

                $name = lcfirst(preg_replace('~Type$~', '', Utils::getTypeName($className)));
                $result[$name] = new $className();
            }
        }

        return $result;
    }
505841
public function buildRelationshipsMetadata(\SimpleXMLElement $node, $className, \ReflectionClass $reflection)
    {
        $relationships = [];
        foreach ($node->relationship as $relationshipNode) {
            $relationships[] = $this->buildRelationshipMetadata($relationshipNode, $className, $reflection);
        }

        return $relationships;
    }
455536
public function getReflectionClassByNode(AbstractNode $node): ReflectionClass
    {
        $nodeClassName = $this->getClassName($node); //todo: check for class

        return $this->classReflector->reflect($nodeClassName);
    }