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

Breadcrumb

  1. Drupal Core 11.1.x
  2. UnusedUsesSniff.php

function UnusedUsesSniff::process

* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint *

Parameters

int $openTagPointer:

Overrides Sniff::process

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php, line 72

Class

UnusedUsesSniff

Namespace

SlevomatCodingStandard\Sniffs\Namespaces

Code

public function process(File $phpcsFile, $openTagPointer) : void {
    if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) {
        return;
    }
    $startPointer = TokenHelper::findPrevious($phpcsFile, T_NAMESPACE, $openTagPointer - 1) ?? $openTagPointer;
    $fileUnusedNames = UseStatementHelper::getFileUseStatements($phpcsFile);
    $referencedNamesInCode = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $startPointer);
    $referencedNamesInAttributes = ReferencedNameHelper::getAllReferencedNamesInAttributes($phpcsFile, $startPointer);
    $pointersBeforeUseStatements = array_reverse(NamespaceHelper::getAllNamespacesPointers($phpcsFile));
    $allUsedNames = [];
    foreach ([
        $referencedNamesInCode,
        $referencedNamesInAttributes,
    ] as $referencedNames) {
        foreach ($referencedNames as $referencedName) {
            $pointer = $referencedName->getStartPointer();
            $pointerBeforeUseStatements = $this->firstPointerBefore($pointer, $pointersBeforeUseStatements, $startPointer);
            $name = $referencedName->getNameAsReferencedInFile();
            $nameParts = NamespaceHelper::getNameParts($name);
            $nameAsReferencedInFile = $nameParts[0];
            $nameReferencedWithoutSubNamespace = count($nameParts) === 1;
            $uniqueId = $nameReferencedWithoutSubNamespace ? UseStatement::getUniqueId($referencedName->getType(), $nameAsReferencedInFile) : UseStatement::getUniqueId(ReferencedName::TYPE_CLASS, $nameAsReferencedInFile);
            if (NamespaceHelper::isFullyQualifiedName($name) || !array_key_exists($pointerBeforeUseStatements, $fileUnusedNames) || !array_key_exists($uniqueId, $fileUnusedNames[$pointerBeforeUseStatements])) {
                continue;
            }
            $allUsedNames[$pointerBeforeUseStatements][$uniqueId] = true;
        }
    }
    if ($this->searchAnnotations) {
        $tokens = $phpcsFile->getTokens();
        $searchAnnotationsPointer = $startPointer + 1;
        while (true) {
            $docCommentOpenPointer = TokenHelper::findNext($phpcsFile, T_DOC_COMMENT_OPEN_TAG, $searchAnnotationsPointer);
            if ($docCommentOpenPointer === null) {
                break;
            }
            $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer);
            if ($annotations === []) {
                $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1;
                continue;
            }
            $pointerBeforeUseStatements = $this->firstPointerBefore($docCommentOpenPointer - 1, $pointersBeforeUseStatements, $startPointer);
            if (!array_key_exists($pointerBeforeUseStatements, $fileUnusedNames)) {
                $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1;
                continue;
            }
            foreach ($fileUnusedNames[$pointerBeforeUseStatements] as $useStatement) {
                if (!$useStatement->isClass()) {
                    continue;
                }
                $nameAsReferencedInFile = $useStatement->getNameAsReferencedInFile();
                $uniqueId = UseStatement::getUniqueId($useStatement->getType(), $nameAsReferencedInFile);
                foreach ($annotations as $annotation) {
                    if (in_array($annotation->getName(), $this->getIgnoredAnnotations(), true)) {
                        continue;
                    }
                    if ($annotation->isInvalid()) {
                        continue;
                    }
                    $contentsToCheck = [];
                    if ($annotation->getValue() instanceof GenericTagValueNode) {
                        $contentsToCheck[] = $annotation->getName();
                        $contentsToCheck[] = $annotation->getValue()->value;
                    }
                    else {
                        
                        /** @var list<IdentifierTypeNode> $identifierTypeNodes */
                        $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), IdentifierTypeNode::class);
                        
                        /** @var list<DoctrineAnnotation> $doctrineAnnotations */
                        $doctrineAnnotations = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), DoctrineAnnotation::class);
                        
                        /** @var list<ConstFetchNode> $constFetchNodes */
                        $constFetchNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), ConstFetchNode::class);
                        $contentsToCheck = array_filter(array_merge($contentsToCheck, array_map(static function (IdentifierTypeNode $identifierTypeNode) : ?string {
                            if (TypeHintHelper::isSimpleTypeHint($identifierTypeNode->name) || TypeHintHelper::isSimpleUnofficialTypeHints($identifierTypeNode->name) || !TypeHelper::isTypeName($identifierTypeNode->name)) {
                                return null;
                            }
                            return $identifierTypeNode->name;
                        }, $identifierTypeNodes), array_map(function (DoctrineAnnotation $doctrineAnnotation) : ?string {
                            if (in_array($doctrineAnnotation->name, $this->getIgnoredAnnotationNames(), true)) {
                                return null;
                            }
                            return $doctrineAnnotation->name;
                        }, $doctrineAnnotations), array_map(static function (ConstFetchNode $constFetchNode) : string {
                            return $constFetchNode->className;
                        }, $constFetchNodes)));
                    }
                    foreach ($contentsToCheck as $contentToCheck) {
                        if (preg_match('~(?<=^|[^a-z\\\\])(' . preg_quote($nameAsReferencedInFile, '~') . ')(?=\\s|::|\\\\|\\||\\[|$)~im', $contentToCheck) === 0) {
                            continue;
                        }
                        $allUsedNames[$pointerBeforeUseStatements][$uniqueId] = true;
                    }
                }
            }
            $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1;
        }
    }
    foreach ($fileUnusedNames as $pointerBeforeUnusedNames => $unusedNames) {
        $usedNames = $allUsedNames[$pointerBeforeUnusedNames] ?? [];
        foreach (array_diff_key($unusedNames, $usedNames) as $unusedUse) {
            $fullName = $unusedUse->getFullyQualifiedTypeName();
            if ($unusedUse->getNameAsReferencedInFile() !== $fullName && $unusedUse->getNameAsReferencedInFile() !== NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($fullName)) {
                $fullName .= sprintf(' (as %s)', $unusedUse->getNameAsReferencedInFile());
            }
            $fix = $phpcsFile->addFixableError(sprintf('Type %s is not used in this file.', $fullName), $unusedUse->getPointer(), self::CODE_UNUSED_USE);
            if (!$fix) {
                continue;
            }
            $endPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $unusedUse->getPointer()) + 1;
            $phpcsFile->fixer
                ->beginChangeset();
            FixerHelper::removeBetweenIncluding($phpcsFile, $unusedUse->getPointer(), $endPointer);
            $phpcsFile->fixer
                ->endChangeset();
        }
    }
}

API Navigation

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