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

Breadcrumb

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

class GitMergeConflictSniff

Hierarchy

  • class \PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\GitMergeConflictSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of GitMergeConflictSniff

File

vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/VersionControl/GitMergeConflictSniff.php, line 15

Namespace

PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl
View source
class GitMergeConflictSniff implements Sniff {
    
    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = [
        'PHP',
        'JS',
        'CSS',
    ];
    
    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array<int|string>
     */
    public function register() {
        return [
            T_OPEN_TAG,
            T_OPEN_TAG_WITH_ECHO,
        ];
    }
    
    //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 int
     */
    public function process(File $phpcsFile, $stackPtr) {
        $tokens = $phpcsFile->getTokens();
        $error = 'Merge conflict boundary found; type: %s';
        $checkTokens = [
            T_SL => true,
            T_SR => true,
            T_IS_IDENTICAL => true,
            T_COMMENT => true,
            T_DOC_COMMENT_STRING => true,
            // PHP + CSS specific.
T_ENCAPSED_AND_WHITESPACE => true,
            // PHP specific.
T_INLINE_HTML => true,
            T_HEREDOC => true,
            T_NOWDOC => true,
            // JS specific.
T_ZSR => true,
        ];
        for ($i = 0; $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$i]['column'] !== 1 || isset($checkTokens[$tokens[$i]['code']]) === false) {
                continue;
            }
            if ($phpcsFile->tokenizerType !== 'JS') {
                switch ($tokens[$i]['code']) {
                    // Check for first non-comment, non-heredoc/nowdoc, non-inline HTML merge conflict opener.
                    case T_SL:
                        if (isset($tokens[$i + 1], $tokens[$i + 2]) !== false && $tokens[$i + 1]['code'] === T_SL && $tokens[$i + 2]['code'] === T_STRING && trim($tokens[$i + 2]['content']) === '<<< HEAD') {
                            $phpcsFile->addError($error, $i, 'OpenerFound', [
                                'opener',
                            ]);
                            $i += 2;
                        }
                        break;
                    // Check for merge conflict closer which was opened in a heredoc/nowdoc.
                    case T_SR:
                        if (isset($tokens[$i + 1], $tokens[$i + 2], $tokens[$i + 3], $tokens[$i + 4]) !== false && $tokens[$i + 1]['code'] === T_SR && $tokens[$i + 2]['code'] === T_SR && $tokens[$i + 3]['code'] === T_GREATER_THAN && $tokens[$i + 4]['code'] === T_WHITESPACE && $tokens[$i + 4]['content'] === ' ') {
                            $phpcsFile->addError($error, $i, 'CloserFound', [
                                'closer',
                            ]);
                            $i += 4;
                        }
                        break;
                    // Check for merge conflict delimiter which opened in a CSS comment and closed outside.
                    case T_IS_IDENTICAL:
                        if (isset($tokens[$i + 1], $tokens[$i + 2], $tokens[$i + 3]) !== false && $tokens[$i + 1]['code'] === T_IS_IDENTICAL && $tokens[$i + 2]['code'] === T_EQUAL && $tokens[$i + 3]['code'] === T_WHITESPACE && $tokens[$i + 3]['content'] === "\n") {
                            $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                'delimiter',
                            ]);
                            $i += 3;
                        }
                        break;
                    // - Check for delimiters and closers.
                    // - Inspect heredoc/nowdoc content, comments and inline HTML.
                    // - Check for subsequent merge conflict openers after the first broke the tokenizer.
                    case T_ENCAPSED_AND_WHITESPACE:
                    case T_COMMENT:
                    case T_DOC_COMMENT_STRING:
                    case T_INLINE_HTML:
                    case T_HEREDOC:
                    case T_NOWDOC:
                        if (substr($tokens[$i]['content'], 0, 12) === '<<<<<<< HEAD') {
                            $phpcsFile->addError($error, $i, 'OpenerFound', [
                                'opener',
                            ]);
                            break;
                        }
                        else {
                            if (substr($tokens[$i]['content'], 0, 8) === '>>>>>>> ') {
                                $phpcsFile->addError($error, $i, 'CloserFound', [
                                    'closer',
                                ]);
                                break;
                            }
                        }
                        if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
                            if ($tokens[$i]['content'] === '=======' && $tokens[$i + 1]['code'] === T_DOC_COMMENT_WHITESPACE) {
                                $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                    'delimiter',
                                ]);
                                break;
                            }
                        }
                        else {
                            if ($tokens[$i]['content'] === "=======\n") {
                                $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                    'delimiter',
                                ]);
                            }
                        }
                        break;
                }
                
                //end switch
            }
            else {
                // Javascript file.
                switch ($tokens[$i]['code']) {
                    // Merge conflict opener.
                    case T_SL:
                        if (isset($tokens[$i + 1], $tokens[$i + 2], $tokens[$i + 3], $tokens[$i + 4], $tokens[$i + 5]) !== false && $tokens[$i + 1]['code'] === T_SL && $tokens[$i + 2]['code'] === T_SL && $tokens[$i + 3]['code'] === T_LESS_THAN && $tokens[$i + 4]['code'] === T_WHITESPACE && trim($tokens[$i + 5]['content']) === 'HEAD') {
                            $phpcsFile->addError($error, $i, 'OpenerFound', [
                                'opener',
                            ]);
                            $i += 5;
                        }
                        break;
                    // Check for merge conflict delimiter.
                    case T_IS_IDENTICAL:
                        if (isset($tokens[$i + 1], $tokens[$i + 2], $tokens[$i + 3]) !== false && $tokens[$i + 1]['code'] === T_IS_IDENTICAL && $tokens[$i + 2]['code'] === T_EQUAL && $tokens[$i + 3]['code'] === T_WHITESPACE && $tokens[$i + 3]['content'] === "\n") {
                            $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                'delimiter',
                            ]);
                            $i += 3;
                        }
                        break;
                    // Merge conflict closer.
                    case T_ZSR:
                        if ($tokens[$i]['code'] === T_ZSR && isset($tokens[$i + 1], $tokens[$i + 2]) === true && $tokens[$i + 1]['code'] === T_ZSR && $tokens[$i + 2]['code'] === T_GREATER_THAN) {
                            $phpcsFile->addError($error, $i, 'CloserFound', [
                                'closer',
                            ]);
                            $i += 2;
                        }
                        break;
                    // Check for merge conflicts in all comments.
                    case T_COMMENT:
                    case T_DOC_COMMENT_STRING:
                        if (substr($tokens[$i]['content'], 0, 12) === '<<<<<<< HEAD') {
                            $phpcsFile->addError($error, $i, 'OpenerFound');
                            break;
                        }
                        else {
                            if (substr($tokens[$i]['content'], 0, 8) === '>>>>>>> ') {
                                $phpcsFile->addError($error, $i, 'CloserFound', [
                                    'closer',
                                ]);
                                break;
                            }
                        }
                        if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
                            if ($tokens[$i]['content'] === '=======' && $tokens[$i + 1]['code'] === T_DOC_COMMENT_WHITESPACE) {
                                $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                    'delimiter',
                                ]);
                                break;
                            }
                        }
                        else {
                            if ($tokens[$i]['content'] === "=======\n") {
                                $phpcsFile->addError($error, $i, 'DelimiterFound', [
                                    'delimiter',
                                ]);
                            }
                        }
                        break;
                }
                
                //end switch
            }
            
            //end if
        }
        
        //end for
        // Ignore the rest of the file.
        return $phpcsFile->numTokens;
    }
    
    //end process()

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
GitMergeConflictSniff::$supportedTokenizers public property A list of tokenizers this sniff supports.
GitMergeConflictSniff::process public function Processes this test, when one of its tokens is encountered. Overrides Sniff::process
GitMergeConflictSniff::register public function Returns an array of tokens this test wants to listen for. Overrides Sniff::register
RSS feed
Powered by Drupal