@param \PHPMD\AbstractNode $node
@param \Roave\BetterReflection\Reflection\ReflectionClass $reflectionNodeClass

@return string[]
489942
public function getRelationNames(AbstractNode $node, ReflectionClass $reflectionNodeClass): array
    {
        $relationNames = [];

        $children = $node->findChildrenOfType('MethodPostfix');

        foreach ($children as $child) {
            $relationMethodName = $child->getName();

            if (stripos($relationMethodName, 'join') === false) {
                continue;
            }

            if ($reflectionNodeClass->hasMethod($relationMethodName)) {
                continue;
            }

            $relationName = $this->getRelationNameFormJoinNode($child, $reflectionNodeClass);

            if (!strpos($relationName, '.')) {
                $relationNames[] = $relationName;

                continue;
            }

            $embeddedRelationNames = explode('.', $relationName);

            foreach ($embeddedRelationNames as $relationName) {
                $relationNames[] = $relationName;
            }
        }

        return array_unique(array_filter($relationNames));
    }
979662
private function getChildren(NodeInterface $node)
    {
        $result = [];
        foreach ($node->getNodes() as $child) {
            $result[$child->getIdentifier()] = $child;
        }

        return $result;
    }
1263377
protected function getAllParentClassNames(ReflectionClass $reflector)
    {
        $classes = [];

        if ($parent = $reflector->getParentClass()) {
            /**
             * @var \ReflectionClass $parent
             */
            if ( ! $parent->isAbstract()) {
                $classes[] = $parent->getName();
            } else {
                $classes[] = sprintf("%s (abstract)", $parent->getName());
            }

            $classes = array_merge($classes, $this->getAllParentClassNames($parent));
        }

        return $classes;
    }
255323
public function generate(ReflectionClass $originalClass) : array
    {
        $ast = [new Class_($originalClass->getShortName())];

        $namespace = $originalClass->getNamespaceName();
        if ($namespace) {
            $ast = [new Namespace_(new Name(explode('\\', $namespace)), $ast)];
        }

        $implementor = new NodeTraverser();
        $implementor->addVisitor(new HydratorMethodsVisitor($originalClass));
        $implementor->addVisitor(new ClassImplementorVisitor($originalClass->getName(), [HydratorInterface::class]));

        return $implementor->traverse($ast);
    }
448833
public function loadMetadataForClass(\ReflectionClass $class)
    {
        $classMetadata = new ClassMetadata($class->name);
        $classMetadata->fileResources[] = $class->getFileName();

        foreach ($this->reader->getClassAnnotations($class) as $annotation) {
            if ($annotation instanceof NamespaceNode) {
                $classMetadata->addGraphNamespace($annotation);
            }

            if ($annotation instanceof GraphNode) {
                $classMetadata->addGraphMetadata($annotation, new MetadataValue($annotation->value));
            }
        }

        foreach ($class->getProperties() as $property) {
            foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
                if ($annotation instanceof GraphNode) {
                    $classMetadata->addGraphMetadata($annotation, new PropertyMetadata($class->name, $property->name));
                }
            }
        }

        foreach ($class->getMethods() as $method) {
            foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
                if ($annotation instanceof GraphNode) {
                    $classMetadata->addGraphMetadata($annotation, new MethodMetadata($class->name, $method->name));
                }
            }
        }

        return $classMetadata;
    }
242157
protected function getQueryNodes(AbstractNode $node): array
    {
        $methodPostfix = $node->findChildrenOfType('MethodPostfix');
        $classOrInterfaceReference = $node->findChildrenOfType('ClassOrInterfaceReference');

        return array_merge($methodPostfix, $classOrInterfaceReference);
    }
372622
protected function collectPatterns(ClassNode $class)
    {
        $patterns = [];
        foreach ($this->patterns as [$srcPattern, $targetPattern, $message]) {
            if (preg_match($srcPattern, $class->getNamespaceName())) {
                $patterns[] = [$srcPattern, $targetPattern, $message];
            }
        }

        return $patterns;
    }
504965
private function getClassProperties(ReflectionClass $reflectionClass)
    {
        $properties = $reflectionClass->getProperties();

        return array_filter(
            array_filter(array_map(
                [$this, 'getAccessibleProperty'],
                array_combine(
                    array_map([$this, 'getLogicalName'], $properties),
                    $properties
                )
            )),
            [$this, 'isInstanceProperty']
        );
    }
1030776
protected function getRelationNameFromJoinParams(AbstractNode $joinNode, ReflectionClass $reflectionNodeClass): ?string
    {
        //todo: refactoring
        $relationArgument = $joinNode->getFirstChildOfType('Arguments');
        $stringRelationArgument = $relationArgument->getFirstChildOfType('Literal');

        if ($stringRelationArgument !== null) {
            $relationArgumentName = trim($stringRelationArgument->getName(), '\'');

            if (!ctype_alpha($relationArgumentName)) {
                return null;
            }

            return $relationArgumentName;
        }

        $constRelationArgument = $relationArgument->getFirstChildOfType('ConstantPostfix');

        if ($constRelationArgument !== null) {
            return $reflectionNodeClass->getConstant($constRelationArgument->getName());
        }

        return null;
    }
342057
private function decodeArrayNode(\DOMNode $node): array
    {
        $data = [];
        foreach ($node->childNodes as $childNode) {
            if ($childNode instanceof \DOMText) {
                continue;
            }

            $data[] = $this->decodeNode($childNode);
        }

        return $data;
    }
445348
public function getFilters(\ReflectionClass $reflectionClass)
    {
        if ($this->isProduction()) {
            $this->grid->getFilter()->getFields();
        }

        $properties = $reflectionClass->getProperties(\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED);
        /** @var \ReflectionProperty $property */
        foreach ($properties as $property) {
            $propertyAnnotations = $this->extractorFactory->extract($property, Extractor::PROPERTY_ANNOTATION);
            foreach ($propertyAnnotations as $annotation) {
                if ($annotation instanceof Filter) {
                    $fields[] = $property->getName();
                }
            }
        }

        return !empty($fields) ? $fields : $this->grid->getFilter()->getFields();
    }
806448
private function generateClassCode(\ReflectionClass $rc) : array
    {
        $mocked_class_name = self::generateMockClassName($rc);
        $namespace = $rc->getNamespaceName();
        $mock_target_class = $rc->getShortName();
        $methods = $rc->getMethods();
        
        $methods = array_filter($methods, function($item){
            /** @var \ReflectionMethod $item */
            return Util::isAllBitSet($item->getModifiers(), \ReflectionMethod::IS_ABSTRACT);
        });
        
        // first line
        $code[] = '<?php';
        
        // namespaces
        if (!empty($namespace)){
            $code[] = 'namespace ' . $namespace . ';';
        }
        
        // uses
        $code[] = '';
        foreach(self::getMethodRequiredClassesByClass($rc) as $rc_){
            $code[] = 'use ' . $rc_->getName() . ';';
        }
        
        // comment
        $code[] = '';
        $code[] = '/**';
        $code[] = ' * Mock class for: ' . $rc->getName();
        $code[] = ' * Generated by stk2k/Decoy';
        $code[] = ' */';
        
        // class definition
        if ($rc->isInterface()){
            $code[] = Code::PHP_CLASS . ' ' . $mocked_class_name .  ' ' . Code::PHP_IMPLEMENTS . ' ' . $mock_target_class;
        }
        else{
            $code[] = Code::PHP_CLASS . ' ' . $mocked_class_name .  ' ' . Code::PHP_EXTENDS . ' ' . $mock_target_class;
        }
        $code[] = '{';
        foreach($methods as $rm){
            $code = array_merge($code, $this->generateMethodCode($rm));
        }
        $code[] = '}';
        
        return array($code, $mocked_class_name, $namespace);
    }
872138
public function getPropertiesArray(NodeInterface $node)
    {
        $properties = [];
        foreach ($node->getNodeType()->getProperties() as $propertyName => $propertyConfiguration) {
            if ($propertyName[0] === '_' && $propertyName[1] === '_') {
                // skip fully-private properties
                continue;
            }

            $properties[$propertyName] = $this->getProperty($node, $propertyName);
        }

        return $properties;
    }
599549
public function find(AbstractNode $node): Collection
    {
        $results = new Collection;
        foreach ($this->selectors as $selector) {
            $nodes = [$node];
            if (count($selector) == 0) {
                continue;
            }

            $options = [];
            foreach ($selector as $rule) {
                if ($rule['alterNext']) {
                    $options[] = $this->alterNext($rule);
                    continue;
                }
                $nodes = $this->seek($nodes, $rule, $options);
                // clear the options
                $options = [];
            }

            // this is the final set of nodes
            foreach ($nodes as $result) {
                $results[] = $result;
            }
        }

        return $results;
    }
236185
public function getModuleNames(AbstractNode $node): array
    {
        $docBlock = $this->getDocBlock($node);

        if ($docBlock === null) {
            return [];
        }

        $moduleTags = $docBlock->getTagsByName(static::TAG_MODULE);
        $moduleTags = $this->docBlockMapper->tagsToArray($moduleTags);

        return $moduleTags[static::TAG_MODULE] ?? [];
    }
412862
protected function getClassProperties(\ReflectionClass $refClass)
    {
        $props = [];

        //fields from parents, including private fields
        $currentClass = $refClass;
        while ($parent = $currentClass->getParentClass()) {
            foreach ($parent->getProperties() as $prop) {
                $props[$prop->name] = $prop;
            }
            $currentClass = $parent;
        }

        foreach ($refClass->getProperties() as $prop) {
            $props[$prop->name] = $prop;
        }

        return $props;
    }
301824
public function getConditions(ReflectionClass $class): array
    {
        $annotations   = [];
        $parents = [];

        $this->getParentClasses($class, $parents);
        $this->getInterfaces($class, $parents);

        foreach ($parents as $parent) {
            $annotations[] = $this->annotationReader->getClassAnnotations($parent);
        }

        if (\count($annotations)) {
            $annotations = \array_merge(...$annotations);
        }

        return $this->filterContractAnnotation($annotations);
    }