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

Breadcrumb

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

class UselessSemicolonSniff

Hierarchy

  • class \SlevomatCodingStandard\Sniffs\PHP\UselessSemicolonSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of UselessSemicolonSniff

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.php, line 24

Namespace

SlevomatCodingStandard\Sniffs\PHP
View source
class UselessSemicolonSniff implements Sniff {
    public const CODE_USELESS_SEMICOLON = 'UselessSemicolon';
    
    /**
     * @return array<int, (int|string)>
     */
    public function register() : array {
        return [
            T_SEMICOLON,
        ];
    }
    
    /**
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     * @param int $semicolonPointer
     */
    public function process(File $phpcsFile, $semicolonPointer) : void {
        $this->checkMultipleSemicolons($phpcsFile, $semicolonPointer);
        $this->checkSemicolonAtTheBeginningOfScope($phpcsFile, $semicolonPointer);
        $this->checkSemicolonAfterScope($phpcsFile, $semicolonPointer);
    }
    private function checkMultipleSemicolons(File $phpcsFile, int $semicolonPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1);
        if ($tokens[$previousPointer]['code'] !== T_SEMICOLON) {
            return;
        }
        $possibleEndScopePointer = TokenHelper::findNextLocal($phpcsFile, T_CLOSE_PARENTHESIS, $semicolonPointer + 1);
        if ($possibleEndScopePointer !== null && $tokens[$possibleEndScopePointer]['parenthesis_opener'] < $semicolonPointer && array_key_exists('parenthesis_owner', $tokens[$possibleEndScopePointer]) && $tokens[$tokens[$possibleEndScopePointer]['parenthesis_owner']]['code'] === T_FOR) {
            return;
        }
        $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON);
        if (!$fix) {
            return;
        }
        $this->removeUselessSemicolon($phpcsFile, $semicolonPointer);
    }
    private function checkSemicolonAtTheBeginningOfScope(File $phpcsFile, int $semicolonPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1);
        if (!in_array($tokens[$previousPointer]['code'], [
            T_OPEN_TAG,
            T_OPEN_CURLY_BRACKET,
        ], true)) {
            return;
        }
        $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON);
        if (!$fix) {
            return;
        }
        $this->removeUselessSemicolon($phpcsFile, $semicolonPointer);
    }
    private function checkSemicolonAfterScope(File $phpcsFile, int $semicolonPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1);
        if ($tokens[$previousPointer]['code'] !== T_CLOSE_CURLY_BRACKET) {
            return;
        }
        if (!array_key_exists('scope_condition', $tokens[$previousPointer])) {
            return;
        }
        $scopeOpenerPointer = $tokens[$previousPointer]['scope_condition'];
        if (in_array($tokens[$scopeOpenerPointer]['code'], [
            T_CLOSURE,
            T_FN,
            T_ANON_CLASS,
            T_MATCH,
        ], true)) {
            return;
        }
        $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON);
        if (!$fix) {
            return;
        }
        $this->removeUselessSemicolon($phpcsFile, $semicolonPointer);
    }
    private function removeUselessSemicolon(File $phpcsFile, int $semicolonPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $fixStartPointer = $semicolonPointer;
        do {
            if ($tokens[$fixStartPointer - 1]['code'] !== T_WHITESPACE) {
                break;
            }
            $fixStartPointer--;
            if ($tokens[$fixStartPointer]['content'] === $phpcsFile->eolChar) {
                break;
            }
        } while (true);
        $fixEndPointer = $semicolonPointer;
        while ($fixEndPointer < count($tokens) - 1) {
            if ($tokens[$fixEndPointer + 1]['code'] !== T_WHITESPACE) {
                break;
            }
            if ($tokens[$fixEndPointer + 1]['content'] === $phpcsFile->eolChar) {
                break;
            }
            $fixEndPointer++;
        }
        $phpcsFile->fixer
            ->beginChangeset();
        FixerHelper::removeBetweenIncluding($phpcsFile, $fixStartPointer, $fixEndPointer);
        $phpcsFile->fixer
            ->endChangeset();
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
UselessSemicolonSniff::checkMultipleSemicolons private function
UselessSemicolonSniff::checkSemicolonAfterScope private function
UselessSemicolonSniff::checkSemicolonAtTheBeginningOfScope private function
UselessSemicolonSniff::CODE_USELESS_SEMICOLON public constant
UselessSemicolonSniff::process public function * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
*
Overrides Sniff::process
UselessSemicolonSniff::register public function * Overrides Sniff::register
UselessSemicolonSniff::removeUselessSemicolon private function
RSS feed
Powered by Drupal