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

Breadcrumb

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

function RequireExplicitAssertionSniff::process

* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint *

Parameters

int $docCommentOpenPointer:

Overrides Sniff::process

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php, line 69

Class

RequireExplicitAssertionSniff

Namespace

SlevomatCodingStandard\Sniffs\PHP

Code

public function process(File $phpcsFile, $docCommentOpenPointer) : void {
    $tokens = $phpcsFile->getTokens();
    $tokenCodes = [
        T_VARIABLE,
        T_FOREACH,
        T_WHILE,
        T_LIST,
        T_OPEN_SHORT_ARRAY,
    ];
    $commentClosePointer = $tokens[$docCommentOpenPointer]['comment_closer'];
    $codePointer = TokenHelper::findFirstNonWhitespaceOnNextLine($phpcsFile, $commentClosePointer);
    if ($codePointer === null || !in_array($tokens[$codePointer]['code'], $tokenCodes, true)) {
        $firstPointerOnPreviousLine = TokenHelper::findFirstNonWhitespaceOnPreviousLine($phpcsFile, $docCommentOpenPointer);
        if ($firstPointerOnPreviousLine === null || !in_array($tokens[$firstPointerOnPreviousLine]['code'], $tokenCodes, true)) {
            return;
        }
        $codePointer = $firstPointerOnPreviousLine;
    }
    
    /** @var list<Annotation<VarTagValueNode>> $variableAnnotations */
    $variableAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer, '@var');
    if (count($variableAnnotations) === 0) {
        return;
    }
    foreach (array_reverse($variableAnnotations) as $variableAnnotation) {
        if ($variableAnnotation->isInvalid()) {
            continue;
        }
        $variableName = $variableAnnotation->getValue()->variableName;
        if ($variableName === '') {
            continue;
        }
        $variableAnnotationType = $variableAnnotation->getValue()->type;
        if ($variableAnnotationType instanceof UnionTypeNode || $variableAnnotationType instanceof IntersectionTypeNode) {
            foreach ($variableAnnotationType->types as $typeNode) {
                if (!$this->isValidTypeNode($typeNode)) {
                    continue 2;
                }
            }
        }
        elseif (!$this->isValidTypeNode($variableAnnotationType)) {
            continue;
        }
        
        /** @var IdentifierTypeNode|ThisTypeNode|UnionTypeNode|GenericTypeNode $variableAnnotationType */
        $variableAnnotationType = $variableAnnotationType;
        $assertion = $this->createAssert($variableName, $variableAnnotationType);
        if ($assertion === null) {
            continue;
        }
        if ($tokens[$codePointer]['code'] === T_VARIABLE) {
            $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $codePointer + 1);
            if ($tokens[$pointerAfterVariable]['code'] !== T_EQUAL) {
                continue;
            }
            if ($variableName !== $tokens[$codePointer]['content']) {
                continue;
            }
            $pointerToAddAssertion = $this->getNextSemicolonInSameScope($phpcsFile, $codePointer, $codePointer + 1);
            $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer);
        }
        elseif ($tokens[$codePointer]['code'] === T_LIST) {
            $listParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $codePointer + 1);
            $variablePointerInList = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $listParenthesisOpener + 1, $tokens[$listParenthesisOpener]['parenthesis_closer']);
            if ($variablePointerInList === null) {
                continue;
            }
            $pointerToAddAssertion = $this->getNextSemicolonInSameScope($phpcsFile, $codePointer, $codePointer + 1);
            $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer);
        }
        elseif ($tokens[$codePointer]['code'] === T_OPEN_SHORT_ARRAY) {
            $pointerAfterList = TokenHelper::findNextEffective($phpcsFile, $tokens[$codePointer]['bracket_closer'] + 1);
            if ($tokens[$pointerAfterList]['code'] !== T_EQUAL) {
                continue;
            }
            $variablePointerInList = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $codePointer + 1, $tokens[$codePointer]['bracket_closer']);
            if ($variablePointerInList === null) {
                continue;
            }
            $pointerToAddAssertion = $this->getNextSemicolonInSameScope($phpcsFile, $codePointer, $tokens[$codePointer]['bracket_closer'] + 1);
            $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer);
        }
        else {
            if ($tokens[$codePointer]['code'] === T_WHILE) {
                $variablePointerInWhile = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $tokens[$codePointer]['parenthesis_opener'] + 1, $tokens[$codePointer]['parenthesis_closer']);
                if ($variablePointerInWhile === null) {
                    continue;
                }
                $pointerAfterVariableInWhile = TokenHelper::findNextEffective($phpcsFile, $variablePointerInWhile + 1);
                if ($tokens[$pointerAfterVariableInWhile]['code'] !== T_EQUAL) {
                    continue;
                }
            }
            else {
                $asPointer = TokenHelper::findNext($phpcsFile, T_AS, $tokens[$codePointer]['parenthesis_opener'] + 1, $tokens[$codePointer]['parenthesis_closer']);
                $variablePointerInForeach = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $asPointer + 1, $tokens[$codePointer]['parenthesis_closer']);
                if ($variablePointerInForeach === null) {
                    continue;
                }
            }
            $pointerToAddAssertion = $tokens[$codePointer]['scope_opener'];
            $indentation = IndentationHelper::addIndentation(IndentationHelper::getIndentation($phpcsFile, $codePointer));
        }
        $fix = $phpcsFile->addFixableError('Use assertion instead of inline documentation comment.', $variableAnnotation->getStartPointer(), self::CODE_REQUIRED_EXPLICIT_ASSERTION);
        if (!$fix) {
            continue;
        }
        $phpcsFile->fixer
            ->beginChangeset();
        FixerHelper::removeBetweenIncluding($phpcsFile, $variableAnnotation->getStartPointer(), $variableAnnotation->getEndPointer());
        $docCommentUseful = false;
        $docCommentClosePointer = $tokens[$docCommentOpenPointer]['comment_closer'];
        for ($i = $docCommentOpenPointer + 1; $i < $docCommentClosePointer; $i++) {
            $tokenContent = trim($phpcsFile->fixer
                ->getTokenContent($i));
            if ($tokenContent === '' || $tokenContent === '*') {
                continue;
            }
            $docCommentUseful = true;
            break;
        }
        $pointerBeforeDocComment = TokenHelper::findPreviousContent($phpcsFile, T_WHITESPACE, $phpcsFile->eolChar, $docCommentOpenPointer - 1);
        $pointerAfterDocComment = TokenHelper::findNextContent($phpcsFile, T_WHITESPACE, $phpcsFile->eolChar, $docCommentClosePointer + 1);
        if (!$docCommentUseful) {
            FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeDocComment + 1, $pointerAfterDocComment);
        }
        if ($pointerToAddAssertion < $docCommentClosePointer && array_key_exists($pointerAfterDocComment + 1, $tokens)) {
            $phpcsFile->fixer
                ->addContentBefore($pointerAfterDocComment + 1, $indentation . $assertion . $phpcsFile->eolChar);
        }
        else {
            $phpcsFile->fixer
                ->addContent($pointerToAddAssertion, $phpcsFile->eolChar . $indentation . $assertion);
        }
        $phpcsFile->fixer
            ->endChangeset();
    }
}
RSS feed
Powered by Drupal