Retrieve the class type hint when it is qualified.

@param Node\Name             $node    The name node to parse.
@param PhpFileModelInterface $phpFile The php file.

@return string The class type hint.
545058
private function getQualifiedClassType(Node\Name $node, PhpFileModelInterface $phpFile): string
    {
        $path      = $node->toString();
        $firstPart = $node->getFirst();

        if ($phpFile->hasUse($firstPart)) {
            return str_replace($firstPart, $phpFile->getUse($firstPart), $path);
        }
        if ($phpFile->getNamespace() !== null
            && $firstPart === $phpFile->getNamespace()[count($phpFile->getNamespace()) - 1]
        ) {
            return str_replace($firstPart, $phpFile->getNamespaceString(), $path);
        }
        return $phpFile->getNamespaceString() . '\\' . $path;
    }
391301
private function getDocumentFromNode(NodeInterface $node)
    {
        $metadata = $this->metadataFactory->getMetadataForPhpcrNode($node);

        return $this->instantiateFromMetadata($metadata);
    }
233717
public function classFilename(string $element, string $name): string
    {
        $namespace = $this->classNamespace($element, $name);
        $namespace = substr($namespace, strlen($this->baseNamespace()));

        $directory = $this->baseDirectory() . '/' . str_replace('\\', '/', $namespace);

        return rtrim($directory, '/') . '/' . $this->className($element, $name) . '.php';
    }
394576
protected function getClassOrInterfaceName(File $phpCsFile, int $stackPointer): string
    {
        $classOrInterfacePosition = $phpCsFile->findPrevious([T_CLASS, T_INTERFACE], $stackPointer);
        $classOrInterfaceNamePosition = $phpCsFile->findNext(T_STRING, $classOrInterfacePosition);

        return $phpCsFile->getTokens()[$classOrInterfaceNamePosition]['content'];
    }
42974
protected function findClass($file)
    {
        $class = false;
        $namespace = false;
        $tokens = token_get_all(file_get_contents($file));

        if (1 === \count($tokens) && T_INLINE_HTML === $tokens[0][0]) {
            throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the "<?php" start tag at the beginning of the file?', $file));
        }

        for ($i = 0; isset($tokens[$i]); ++$i) {
            $token = $tokens[$i];

            if (!isset($token[1])) {
                continue;
            }

            if (true === $class && T_STRING === $token[0]) {
                return $namespace.'\\'.$token[1];
            }

            if (true === $namespace && T_STRING === $token[0]) {
                $namespace = $token[1];
                while (isset($tokens[++$i][1]) && \in_array($tokens[$i][0], [T_NS_SEPARATOR, T_STRING])) {
                    $namespace .= $tokens[$i][1];
                }
                $token = $tokens[$i];
            }

            if (T_CLASS === $token[0]) {
                // Skip usage of ::class constant and anonymous classes
                $skipClassToken = false;
                for ($j = $i - 1; $j > 0; --$j) {
                    if (!isset($tokens[$j][1])) {
                        break;
                    }

                    if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
                        $skipClassToken = true;
                        break;
                    } elseif (!\in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT])) {
                        break;
                    }
                }

                if (!$skipClassToken) {
                    $class = true;
                }
            }

            if (T_NAMESPACE === $token[0]) {
                $namespace = true;
            }
        }

        return false;
    }
425544
private function classMember() {
    $node = new ClassMemberNode();
    $this->mustMatch(T_VARIABLE, $node, 'name', TRUE);
    if ($this->tryMatch('=', $node)) {
      $node->addChild($this->staticScalar(), 'value');
    }
    return $node;
  }
455536
public function getReflectionClassByNode(AbstractNode $node): ReflectionClass
    {
        $nodeClassName = $this->getClassName($node); //todo: check for class

        return $this->classReflector->reflect($nodeClassName);
    }
338963
public static function getDefinedFqn($node)
    {
        $parent = $node->parent;
        // Anonymous classes don't count as a definition
        // INPUT                    OUTPUT:
        // namespace A\B;
        // class C { }              A\B\C
        // interface C { }          A\B\C
        // trait C { }              A\B\C
        if (
            $node instanceof PhpParser\ClassLike
        ) {
            $className = (string)$node->getNamespacedName();
            // An (invalid) class declaration without a name will have an empty string as name,
            // but should not define an FQN
            if ($className === '') {
                return null;
            }
            return $className;
        }

        // INPUT                   OUTPUT:
        // namespace A\B;           A\B
        if ($node instanceof Node\Statement\NamespaceDefinition && $node->name instanceof Node\QualifiedName) {
            $name = (string) PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents());
            return $name === "" ? null : $name;
        }

        // INPUT                   OUTPUT:
        // namespace A\B;
        // function a();           A\B\a();
        if ($node instanceof Node\Statement\FunctionDeclaration) {
            // Function: use functionName() as the name
            $name = (string)$node->getNamespacedName();
            return $name === "" ? null : $name . '()';
        }

        // INPUT                        OUTPUT
        // namespace A\B;
        // class C {
        //   function a () {}           A\B\C->a()
        //   static function b() {}     A\B\C::b()
        // }
        if ($node instanceof Node\MethodDeclaration) {
            // Class method: use ClassName->methodName() as name
            $class = $node->getFirstAncestor(
                Node\Expression\ObjectCreationExpression::class,
                PhpParser\ClassLike::class
            );
            if (!isset($class->name)) {
                // Ignore anonymous classes
                return null;
            }
            if ($node->isStatic()) {
                return (string)$class->getNamespacedName() . '::' . $node->getName() . '()';
            } else {
                return (string)$class->getNamespacedName() . '->' . $node->getName() . '()';
            }
        }

        // INPUT                        OUTPUT
        // namespace A\B;
        // class C {
        //   static $a = 4, $b = 4      A\B\C::$a, A\B\C::$b
        //   $a = 4, $b = 4             A\B\C->$a, A\B\C->$b // TODO verify variable name
        // }
        if (
            ($propertyDeclaration = ParserHelpers\tryGetPropertyDeclaration($node)) !== null &&
            ($classDeclaration =
                $node->getFirstAncestor(
                    Node\Expression\ObjectCreationExpression::class,
                    PhpParser\ClassLike::class
                )
            ) !== null && isset($classDeclaration->name)) {
            $name = $node->getName();
            if ($propertyDeclaration->isStatic()) {
                // Static Property: use ClassName::$propertyName as name
                return (string)$classDeclaration->getNamespacedName() . '::$' . $name;
            }

            // Instance Property: use ClassName->propertyName as name
            return (string)$classDeclaration->getNamespacedName() . '->' . $name;
        }

        // INPUT                        OUTPUT
        // namespace A\B;
        // const FOO = 5;               A\B\FOO
        // class C {
        //   const $a, $b = 4           A\B\C::$a(), A\B\C::$b
        // }
        if (($constDeclaration = ParserHelpers\tryGetConstOrClassConstDeclaration($node)) !== null) {
            if ($constDeclaration instanceof Node\Statement\ConstDeclaration) {
                // Basic constant: use CONSTANT_NAME as name
                return (string)$node->getNamespacedName();
            }

            // Class constant: use ClassName::CONSTANT_NAME as name
            $classDeclaration = $constDeclaration->getFirstAncestor(
                Node\Expression\ObjectCreationExpression::class,
                PhpParser\ClassLike::class
            );

            if (!isset($classDeclaration->name)) {
                return null;
            }
            return (string)$classDeclaration->getNamespacedName() . '::' . $node->getName();
        }

        if (ParserHelpers\isConstDefineExpression($node)) {
            return $node->argumentExpressionList->children[0]->expression->getStringContentsText();
        }

        return null;
    }
1309769
public function getClassName(AbstractNode $node): string
    {
        $fullQualifiedName = $node->getFullQualifiedName();
        $fullQualifiedName = explode('::', $fullQualifiedName);

        return array_shift($fullQualifiedName);
    }
588309
protected function inferClassName(File $file) {
    return Code::mapFileToClass($file, $this->classPath->up(), $this->underscoreStyle ? '_' : '\\');
  }
1137407
public function getType( $name, $prefix = null )
	{
		// It can be the case that the type passed in is an array.  This can happen if the type for an
		// element is defined in the schema as simpleContent extending some base type by restriction.
		// In case this could be the case, look for an array with an element key of 'class' and value
		// 'simple'. If found, there should be an element with a key of 'parent'.  Use this.
		if ( is_array( $name ) && isset( $name['class'] ) && isset( $name['parent'] ) )
		{
			$name = $name['parent'];
		}

		if ( strpos( $name, ":" ) === false && is_null( $prefix ) )
		{
			// Assume xs
			$prefix = "xs";
		}

		return $this->hasType( $name, $prefix )
			? $this->types[ is_null( $prefix ) ? $name : "$prefix:$name" ]
			: false;
	}
1214896
protected function getClassName(AbstractNode $node): string
    {
        if ($node instanceof MethodNode) {
            $node = $this->getNodeFromMethodNode($node);
            $parent = $node->getParent();

            return $parent->getNamespacedName();
        }

        return $node->getFullQualifiedName();
    }
153049
public function getNodeType()
	{
		static $nodeType;
		return $nodeType??$nodeType= $this->nodeType??(static function($className){return strtolower(preg_replace('/(?<=\\w)([A-Z])/','_$1',preg_replace('/^(?:\\w+\\\\)*(\\w+)Node$/','$1',$className)));})(get_class($this));
	}
1271682
public function enterNode(PhpParser\Node $node)
    {
        $attrs = $node->getAttributes();

        if ($cs = $node->getComments()) {
            $new_comments = [];

            foreach ($cs as $c) {
                if ($c instanceof PhpParser\Comment\Doc) {
                    $new_comments[] = new PhpParser\Comment\Doc(
                        $c->getText(),
                        $c->getLine() + $this->line_offset,
                        $c->getFilePos() + $this->file_offset
                    );
                } else {
                    $new_comments[] = new PhpParser\Comment(
                        $c->getText(),
                        $c->getLine() + $this->line_offset,
                        $c->getFilePos() + $this->file_offset
                    );
                }
            }

            $node->setAttribute('comments', $new_comments);
        }

        /** @psalm-suppress MixedOperand */
        $node->setAttribute('startFilePos', $attrs['startFilePos'] + $this->file_offset);
        /** @psalm-suppress MixedOperand */
        $node->setAttribute('endFilePos', $attrs['endFilePos'] + $this->file_offset);
        /** @psalm-suppress MixedOperand */
        $node->setAttribute('startLine', $attrs['startLine'] + $this->line_offset);
    }
926555
protected function useCaseNodeToDslText(NodeInterface $node)
    {
        $dslText = sprintf(
            $this->nodeTypeToDslText[Node::TYPE_USE_CASE],
            $this->getFilter()->filter($node->getNodeName())
        );

        return $dslText;
    }
1186759
private function createInterface(Interface_ $node)
    {
        $ref = new RefClass();

        $ref->isInterface = true;
        $ref->fileName    = $this->file;
        $ref->name        = $this->getFullClassName((string)$node->name);
        $ref->docComment  = $this->createDocComment($node);

        $ref->startLine = $node->getLine();

        foreach ($node->extends as $implement) {
            $ref->implements[] = $this->getFullClassName($implement);
        }

        return $ref;
    }
995902
private function getClassValidator($node)
    {
        $classStringName = $node['_type'].'_validator';
        $classStringNamespace = '\Volan\Validator\\';

        $classNames = [];
        $classNames[] = $classStringNamespace.$classStringName;
        $classNames[] = $classStringNamespace.$this->getPSRCompatibleClassName($classStringName);

        if (class_exists($classNames[0])) {
            $validatorClass = new $classNames[0]();
        } elseif (class_exists($classNames[1])) {
            $validatorClass = new $classNames[1]();
        } else {
            throw new Exception("Class validator {$classNames[0]}/{$classNames[1]} not found", ValidatorResult::ERROR_VALIDATOR_CLASS_NOT_FOUND);
        }

        $this->getLogger()->info("Class validator ".get_class($validatorClass)." exists");

        return $validatorClass;
    }