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

Breadcrumb

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

class ForLoopDeclarationSniff

Hierarchy

  • class \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ForLoopDeclarationSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of ForLoopDeclarationSniff

File

vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php, line 16

Namespace

PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures
View source
class ForLoopDeclarationSniff implements Sniff {
    
    /**
     * How many spaces should follow the opening bracket.
     *
     * @var integer
     */
    public $requiredSpacesAfterOpen = 0;
    
    /**
     * How many spaces should precede the closing bracket.
     *
     * @var integer
     */
    public $requiredSpacesBeforeClose = 0;
    
    /**
     * Allow newlines instead of spaces.
     *
     * @var boolean
     */
    public $ignoreNewlines = false;
    
    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = [
        'PHP',
        'JS',
    ];
    
    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array<int|string>
     */
    public function register() {
        return [
            T_FOR,
        ];
    }
    
    //end register()
    
    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
     * @param int                         $stackPtr  The position of the current token in the
     *                                               stack passed in $tokens.
     *
     * @return void
     */
    public function process(File $phpcsFile, $stackPtr) {
        $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen;
        $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose;
        $tokens = $phpcsFile->getTokens();
        $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr);
        if ($openingBracket === false || isset($tokens[$openingBracket]['parenthesis_closer']) === false) {
            $error = 'Possible parse error: no opening/closing parenthesis for FOR keyword';
            $phpcsFile->addWarning($error, $stackPtr, 'NoOpenBracket');
            return;
        }
        $closingBracket = $tokens[$openingBracket]['parenthesis_closer'];
        if ($this->requiredSpacesAfterOpen === 0 && $tokens[$openingBracket + 1]['code'] === T_WHITESPACE) {
            $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, $openingBracket + 1, $closingBracket, true);
            if ($this->ignoreNewlines === false || $tokens[$nextNonWhiteSpace]['line'] === $tokens[$openingBracket]['line']) {
                $error = 'Whitespace found after opening bracket of FOR loop';
                $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen');
                if ($fix === true) {
                    $phpcsFile->fixer
                        ->beginChangeset();
                    for ($i = $openingBracket + 1; $i < $closingBracket; $i++) {
                        if ($tokens[$i]['code'] !== T_WHITESPACE) {
                            break;
                        }
                        $phpcsFile->fixer
                            ->replaceToken($i, '');
                    }
                    $phpcsFile->fixer
                        ->endChangeset();
                }
            }
        }
        else {
            if ($this->requiredSpacesAfterOpen > 0) {
                $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, $openingBracket + 1, $closingBracket, true);
                $spaceAfterOpen = 0;
                if ($tokens[$openingBracket]['line'] !== $tokens[$nextNonWhiteSpace]['line']) {
                    $spaceAfterOpen = 'newline';
                }
                else {
                    if ($tokens[$openingBracket + 1]['code'] === T_WHITESPACE) {
                        $spaceAfterOpen = $tokens[$openingBracket + 1]['length'];
                    }
                }
                if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen && ($this->ignoreNewlines === false || $spaceAfterOpen !== 'newline')) {
                    $error = 'Expected %s spaces after opening bracket; %s found';
                    $data = [
                        $this->requiredSpacesAfterOpen,
                        $spaceAfterOpen,
                    ];
                    $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen', $data);
                    if ($fix === true) {
                        $padding = str_repeat(' ', $this->requiredSpacesAfterOpen);
                        if ($spaceAfterOpen === 0) {
                            $phpcsFile->fixer
                                ->addContent($openingBracket, $padding);
                        }
                        else {
                            $phpcsFile->fixer
                                ->beginChangeset();
                            $phpcsFile->fixer
                                ->replaceToken($openingBracket + 1, $padding);
                            for ($i = $openingBracket + 2; $i < $nextNonWhiteSpace; $i++) {
                                $phpcsFile->fixer
                                    ->replaceToken($i, '');
                            }
                            $phpcsFile->fixer
                                ->endChangeset();
                        }
                    }
                }
                
                //end if
            }
        }
        
        //end if
        $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, $closingBracket - 1, $openingBracket, true);
        $beforeClosefixable = true;
        if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line'] && isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true) {
            $beforeClosefixable = false;
        }
        if ($this->requiredSpacesBeforeClose === 0 && $tokens[$closingBracket - 1]['code'] === T_WHITESPACE && ($this->ignoreNewlines === false || $tokens[$prevNonWhiteSpace]['line'] === $tokens[$closingBracket]['line'])) {
            $error = 'Whitespace found before closing bracket of FOR loop';
            if ($beforeClosefixable === false) {
                $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose');
            }
            else {
                $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose');
                if ($fix === true) {
                    $phpcsFile->fixer
                        ->beginChangeset();
                    for ($i = $closingBracket - 1; $i > $openingBracket; $i--) {
                        if ($tokens[$i]['code'] !== T_WHITESPACE) {
                            break;
                        }
                        $phpcsFile->fixer
                            ->replaceToken($i, '');
                    }
                    $phpcsFile->fixer
                        ->endChangeset();
                }
            }
        }
        else {
            if ($this->requiredSpacesBeforeClose > 0) {
                $spaceBeforeClose = 0;
                if ($tokens[$closingBracket]['line'] !== $tokens[$prevNonWhiteSpace]['line']) {
                    $spaceBeforeClose = 'newline';
                }
                else {
                    if ($tokens[$closingBracket - 1]['code'] === T_WHITESPACE) {
                        $spaceBeforeClose = $tokens[$closingBracket - 1]['length'];
                    }
                }
                if ($this->requiredSpacesBeforeClose !== $spaceBeforeClose && ($this->ignoreNewlines === false || $spaceBeforeClose !== 'newline')) {
                    $error = 'Expected %s spaces before closing bracket; %s found';
                    $data = [
                        $this->requiredSpacesBeforeClose,
                        $spaceBeforeClose,
                    ];
                    if ($beforeClosefixable === false) {
                        $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose', $data);
                    }
                    else {
                        $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose', $data);
                        if ($fix === true) {
                            $padding = str_repeat(' ', $this->requiredSpacesBeforeClose);
                            if ($spaceBeforeClose === 0) {
                                $phpcsFile->fixer
                                    ->addContentBefore($closingBracket, $padding);
                            }
                            else {
                                $phpcsFile->fixer
                                    ->beginChangeset();
                                $phpcsFile->fixer
                                    ->replaceToken($closingBracket - 1, $padding);
                                for ($i = $closingBracket - 2; $i > $prevNonWhiteSpace; $i--) {
                                    $phpcsFile->fixer
                                        ->replaceToken($i, '');
                                }
                                $phpcsFile->fixer
                                    ->endChangeset();
                            }
                        }
                    }
                }
                
                //end if
            }
        }
        
        //end if
        
        /*
         * Check whitespace around each of the semicolon tokens.
         */
        $semicolonCount = 0;
        $semicolon = $openingBracket;
        $targetNestinglevel = 0;
        if (isset($tokens[$openingBracket]['conditions']) === true) {
            $targetNestinglevel = count($tokens[$openingBracket]['conditions']);
        }
        do {
            $semicolon = $phpcsFile->findNext(T_SEMICOLON, $semicolon + 1, $closingBracket);
            if ($semicolon === false) {
                break;
            }
            if (isset($tokens[$semicolon]['conditions']) === true && count($tokens[$semicolon]['conditions']) > $targetNestinglevel) {
                // Semicolon doesn't belong to the for().
                continue;
            }
            ++$semicolonCount;
            $humanReadableCount = 'first';
            if ($semicolonCount !== 1) {
                $humanReadableCount = 'second';
            }
            $humanReadableCode = ucfirst($humanReadableCount);
            $data = [
                $humanReadableCount,
            ];
            // Only examine the space before the first semicolon if the first expression is not empty.
            // If it *is* empty, leave it up to the `SpacingAfterOpen` logic.
            $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, $semicolon - 1, $openingBracket, true);
            if ($semicolonCount !== 1 || $prevNonWhiteSpace !== $openingBracket) {
                if ($tokens[$semicolon - 1]['code'] === T_WHITESPACE) {
                    $error = 'Whitespace found before %s semicolon of FOR loop';
                    $errorCode = 'SpacingBefore' . $humanReadableCode;
                    $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
                    if ($fix === true) {
                        $phpcsFile->fixer
                            ->beginChangeset();
                        for ($i = $semicolon - 1; $i > $prevNonWhiteSpace; $i--) {
                            $phpcsFile->fixer
                                ->replaceToken($i, '');
                        }
                        $phpcsFile->fixer
                            ->endChangeset();
                    }
                }
            }
            // Only examine the space after the second semicolon if the last expression is not empty.
            // If it *is* empty, leave it up to the `SpacingBeforeClose` logic.
            $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, $semicolon + 1, $closingBracket + 1, true);
            if ($semicolonCount !== 2 || $nextNonWhiteSpace !== $closingBracket) {
                if ($tokens[$semicolon + 1]['code'] !== T_WHITESPACE && $tokens[$semicolon + 1]['code'] !== T_SEMICOLON) {
                    $error = 'Expected 1 space after %s semicolon of FOR loop; 0 found';
                    $errorCode = 'NoSpaceAfter' . $humanReadableCode;
                    $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
                    if ($fix === true) {
                        $phpcsFile->fixer
                            ->addContent($semicolon, ' ');
                    }
                }
                else {
                    if ($tokens[$semicolon + 1]['code'] === T_WHITESPACE && $tokens[$nextNonWhiteSpace]['code'] !== T_SEMICOLON) {
                        $spaces = $tokens[$semicolon + 1]['length'];
                        if ($tokens[$semicolon]['line'] !== $tokens[$nextNonWhiteSpace]['line']) {
                            $spaces = 'newline';
                        }
                        if ($spaces !== 1 && ($this->ignoreNewlines === false || $spaces !== 'newline')) {
                            $error = 'Expected 1 space after %s semicolon of FOR loop; %s found';
                            $errorCode = 'SpacingAfter' . $humanReadableCode;
                            $data[] = $spaces;
                            $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data);
                            if ($fix === true) {
                                $phpcsFile->fixer
                                    ->beginChangeset();
                                $phpcsFile->fixer
                                    ->replaceToken($semicolon + 1, ' ');
                                for ($i = $semicolon + 2; $i < $nextNonWhiteSpace; $i++) {
                                    $phpcsFile->fixer
                                        ->replaceToken($i, '');
                                }
                                $phpcsFile->fixer
                                    ->endChangeset();
                            }
                        }
                    }
                }
                
                //end if
            }
            
            //end if
        } while ($semicolonCount < 2);
    }
    
    //end process()

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
ForLoopDeclarationSniff::$ignoreNewlines public property Allow newlines instead of spaces.
ForLoopDeclarationSniff::$requiredSpacesAfterOpen public property How many spaces should follow the opening bracket.
ForLoopDeclarationSniff::$requiredSpacesBeforeClose public property How many spaces should precede the closing bracket.
ForLoopDeclarationSniff::$supportedTokenizers public property A list of tokenizers this sniff supports.
ForLoopDeclarationSniff::process public function Processes this test, when one of its tokens is encountered. Overrides Sniff::process
ForLoopDeclarationSniff::register public function Returns an array of tokens this test wants to listen for. Overrides Sniff::register
RSS feed
Powered by Drupal