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\VersionControlView 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 |