Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x

NamespaceHelper.php

Namespace

SlevomatCodingStandard\Helpers

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/NamespaceHelper.php

View source
<?php

declare (strict_types=1);
namespace SlevomatCodingStandard\Helpers;

use PHP_CodeSniffer\Files\File;
use function array_filter;
use function array_reverse;
use function array_slice;
use function array_values;
use function count;
use function defined;
use function explode;
use function implode;
use function in_array;
use function ltrim;
use function sprintf;
use function strpos;
use const T_NAME_FULLY_QUALIFIED;
use const T_NAMESPACE;
use const T_NS_SEPARATOR;

/**
 * Terms "unqualified", "qualified" and "fully qualified" have the same meaning as described here:
 * http://php.net/manual/en/language.namespaces.rules.php
 *
 * "Canonical" is a fully qualified name without the leading backslash.
 *
 * @internal
 */
class NamespaceHelper {
    public const NAMESPACE_SEPARATOR = '\\';
    
    /**
     * @return list<int>
     */
    public static function getAllNamespacesPointers(File $phpcsFile) : array {
        $tokens = $phpcsFile->getTokens();
        $lazyValue = static function () use ($phpcsFile, $tokens) : array {
            $all = TokenHelper::findNextAll($phpcsFile, T_NAMESPACE, 0);
            $all = array_filter($all, static function ($pointer) use ($phpcsFile, $tokens) {
                $next = TokenHelper::findNextEffective($phpcsFile, $pointer + 1);
                return $next === null || $tokens[$next]['code'] !== T_NS_SEPARATOR;
            });
            return array_values($all);
        };
        return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'namespacePointers', $lazyValue);
    }
    public static function isFullyQualifiedName(string $typeName) : bool {
        return StringHelper::startsWith($typeName, self::NAMESPACE_SEPARATOR);
    }
    public static function isFullyQualifiedPointer(File $phpcsFile, int $pointer) : bool {
        return in_array($phpcsFile->getTokens()[$pointer]['code'], [
            T_NS_SEPARATOR,
            T_NAME_FULLY_QUALIFIED,
        ], true);
    }
    public static function getFullyQualifiedTypeName(string $typeName) : string {
        if (self::isFullyQualifiedName($typeName)) {
            return $typeName;
        }
        return sprintf('%s%s', self::NAMESPACE_SEPARATOR, $typeName);
    }
    public static function hasNamespace(string $typeName) : bool {
        $parts = self::getNameParts($typeName);
        return count($parts) > 1;
    }
    
    /**
     * @return list<string>
     */
    public static function getNameParts(string $name) : array {
        $name = self::normalizeToCanonicalName($name);
        return explode(self::NAMESPACE_SEPARATOR, $name);
    }
    public static function getLastNamePart(string $name) : string {
        return array_slice(self::getNameParts($name), -1)[0];
    }
    public static function getName(File $phpcsFile, int $namespacePointer) : string {
        
        /** @var int $namespaceNameStartPointer */
        $namespaceNameStartPointer = TokenHelper::findNextEffective($phpcsFile, $namespacePointer + 1);
        $namespaceNameEndPointer = TokenHelper::findNextExcluding($phpcsFile, TokenHelper::getNameTokenCodes(), $namespaceNameStartPointer + 1) - 1;
        return TokenHelper::getContent($phpcsFile, $namespaceNameStartPointer, $namespaceNameEndPointer);
    }
    public static function findCurrentNamespacePointer(File $phpcsFile, int $pointer) : ?int {
        $allNamespacesPointers = array_reverse(self::getAllNamespacesPointers($phpcsFile));
        foreach ($allNamespacesPointers as $namespacesPointer) {
            if ($namespacesPointer < $pointer) {
                return $namespacesPointer;
            }
        }
        return null;
    }
    public static function findCurrentNamespaceName(File $phpcsFile, int $anyPointer) : ?string {
        $namespacePointer = self::findCurrentNamespacePointer($phpcsFile, $anyPointer);
        if ($namespacePointer === null) {
            return null;
        }
        return self::getName($phpcsFile, $namespacePointer);
    }
    public static function getUnqualifiedNameFromFullyQualifiedName(string $name) : string {
        $parts = self::getNameParts($name);
        return $parts[count($parts) - 1];
    }
    public static function isQualifiedName(string $name) : bool {
        return strpos($name, self::NAMESPACE_SEPARATOR) !== false;
    }
    public static function normalizeToCanonicalName(string $fullyQualifiedName) : string {
        return ltrim($fullyQualifiedName, self::NAMESPACE_SEPARATOR);
    }
    public static function isTypeInNamespace(string $typeName, string $namespace) : bool {
        return StringHelper::startsWith(self::normalizeToCanonicalName($typeName) . '\\', $namespace . '\\');
    }
    public static function resolveClassName(File $phpcsFile, string $nameAsReferencedInFile, int $currentPointer) : string {
        return self::resolveName($phpcsFile, $nameAsReferencedInFile, ReferencedName::TYPE_CLASS, $currentPointer);
    }
    public static function resolveName(File $phpcsFile, string $nameAsReferencedInFile, string $type, int $currentPointer) : string {
        if (self::isFullyQualifiedName($nameAsReferencedInFile)) {
            return $nameAsReferencedInFile;
        }
        $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $currentPointer);
        $uniqueId = UseStatement::getUniqueId($type, self::normalizeToCanonicalName($nameAsReferencedInFile));
        if (isset($useStatements[$uniqueId])) {
            return sprintf('%s%s', self::NAMESPACE_SEPARATOR, $useStatements[$uniqueId]->getFullyQualifiedTypeName());
        }
        $nameParts = self::getNameParts($nameAsReferencedInFile);
        $firstPartUniqueId = UseStatement::getUniqueId($type, $nameParts[0]);
        if (count($nameParts) > 1 && isset($useStatements[$firstPartUniqueId])) {
            return sprintf('%s%s%s%s', self::NAMESPACE_SEPARATOR, $useStatements[$firstPartUniqueId]->getFullyQualifiedTypeName(), self::NAMESPACE_SEPARATOR, implode(self::NAMESPACE_SEPARATOR, array_slice($nameParts, 1)));
        }
        $name = sprintf('%s%s', self::NAMESPACE_SEPARATOR, $nameAsReferencedInFile);
        if ($type === ReferencedName::TYPE_CONSTANT && defined($name)) {
            return $name;
        }
        $namespaceName = self::findCurrentNamespaceName($phpcsFile, $currentPointer);
        if ($namespaceName !== null) {
            $name = sprintf('%s%s%s', self::NAMESPACE_SEPARATOR, $namespaceName, $name);
        }
        return $name;
    }

}

Classes

Title Deprecated Summary
NamespaceHelper Terms "unqualified", "qualified" and "fully qualified" have the same meaning as described here: http://php.net/manual/en/language.namespaces.rules.php

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal