View source
<?php
namespace Drupal\Sniffs\WhiteSpace;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
class OperatorSpacingSniff implements Sniff {
public $supportedTokenizers = array(
'PHP',
'JS',
);
public $ignoreNewlines = true;
public function register() {
$comparison = Tokens::$comparisonTokens;
$operators = Tokens::$operators;
$assignment = Tokens::$assignmentTokens;
$inlineIf = array(
T_INLINE_THEN,
T_INLINE_ELSE,
);
return array_unique(array_merge($comparison, $operators, $assignment, $inlineIf));
}
public function process(File $phpcsFile, $stackPtr) {
$tokens = $phpcsFile
->getTokens();
if ($tokens[$stackPtr]['code'] === T_EQUAL || $tokens[$stackPtr]['code'] === T_MINUS) {
if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
$parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']);
$bracket = array_pop($parenthesis);
if (isset($tokens[$bracket]['parenthesis_owner']) === true) {
$function = $tokens[$bracket]['parenthesis_owner'];
if ($tokens[$function]['code'] === T_FUNCTION || $tokens[$function]['code'] === T_CLOSURE) {
return;
}
}
}
}
if ($tokens[$stackPtr]['code'] === T_EQUAL) {
if (isset($tokens[$stackPtr + 1]) === true && $tokens[$stackPtr + 1]['code'] === T_BITWISE_AND) {
return;
}
}
if ($tokens[$stackPtr]['code'] === T_INLINE_THEN && $tokens[$stackPtr + 1]['code'] === T_INLINE_ELSE || $tokens[$stackPtr - 1]['code'] === T_INLINE_THEN && $tokens[$stackPtr]['code'] === T_INLINE_ELSE) {
return;
}
if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) {
if ($phpcsFile
->isReference($stackPtr) === true) {
return;
}
if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) {
$error = 'Expected 1 space before "&" operator; 0 found';
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'NoSpaceBeforeAmp');
if ($fix === true) {
$phpcsFile->fixer
->addContentBefore($stackPtr, ' ');
}
$phpcsFile
->recordMetric($stackPtr, 'Space before operator', 0);
}
else {
if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) {
$found = 'newline';
}
else {
$found = $tokens[$stackPtr - 1]['length'];
}
$phpcsFile
->recordMetric($stackPtr, 'Space before operator', $found);
if ($found !== 1 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
$error = 'Expected 1 space before "&" operator; %s found';
$data = array(
$found,
);
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'SpacingBeforeAmp', $data);
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($stackPtr - 1, ' ');
}
}
}
if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
$error = 'Expected 1 space after "&" operator; 0 found';
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'NoSpaceAfterAmp');
if ($fix === true) {
$phpcsFile->fixer
->addContent($stackPtr, ' ');
}
$phpcsFile
->recordMetric($stackPtr, 'Space after operator', 0);
}
else {
if ($tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) {
$found = 'newline';
}
else {
$found = $tokens[$stackPtr + 1]['length'];
}
$phpcsFile
->recordMetric($stackPtr, 'Space after operator', $found);
if ($found !== 1 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
$error = 'Expected 1 space after "&" operator; %s found';
$data = array(
$found,
);
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'SpacingAfterAmp', $data);
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($stackPtr + 1, ' ');
}
}
}
return;
}
if ($tokens[$stackPtr]['code'] === T_MINUS || $tokens[$stackPtr]['code'] === T_PLUS) {
$prev = $phpcsFile
->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($tokens[$prev]['code'] === T_RETURN) {
return;
}
if (isset(Tokens::$operators[$tokens[$prev]['code']]) === true) {
return;
}
if (isset(Tokens::$comparisonTokens[$tokens[$prev]['code']]) === true) {
return;
}
if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) {
return;
}
if (isset(Tokens::$assignmentTokens[$tokens[$prev]['code']]) === true) {
return;
}
$invalidTokens = array(
T_COMMA => true,
T_OPEN_PARENTHESIS => true,
T_OPEN_SQUARE_BRACKET => true,
T_OPEN_SHORT_ARRAY => true,
T_DOUBLE_ARROW => true,
T_COLON => true,
T_INLINE_THEN => true,
T_INLINE_ELSE => true,
T_CASE => true,
);
if (isset($invalidTokens[$tokens[$prev]['code']]) === true) {
return;
}
}
$operator = $tokens[$stackPtr]['content'];
if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) {
$error = "Expected 1 space before \"{$operator}\"; 0 found";
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'NoSpaceBefore');
if ($fix === true) {
$phpcsFile->fixer
->addContentBefore($stackPtr, ' ');
}
$phpcsFile
->recordMetric($stackPtr, 'Space before operator', 0);
}
else {
if (isset(Tokens::$assignmentTokens[$tokens[$stackPtr]['code']]) === false) {
if ($tokens[$stackPtr - 2]['line'] !== $tokens[$stackPtr]['line']) {
$found = 'newline';
}
else {
$found = $tokens[$stackPtr - 1]['length'];
}
$phpcsFile
->recordMetric($stackPtr, 'Space before operator', $found);
if ($found !== 1 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
$error = 'Expected 1 space before "%s"; %s found';
$data = array(
$operator,
$found,
);
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'SpacingBefore', $data);
if ($fix === true) {
$phpcsFile->fixer
->beginChangeset();
if ($found === 'newline') {
$i = $stackPtr - 2;
while ($tokens[$i]['code'] === T_WHITESPACE) {
$phpcsFile->fixer
->replaceToken($i, '');
$i--;
}
}
$phpcsFile->fixer
->replaceToken($stackPtr - 1, ' ');
$phpcsFile->fixer
->endChangeset();
}
}
}
}
if (isset($tokens[$stackPtr + 1]) === false) {
return;
}
if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) {
$error = "Expected 1 space after \"{$operator}\"; 0 found";
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'NoSpaceAfter');
if ($fix === true) {
$phpcsFile->fixer
->addContent($stackPtr, ' ');
}
$phpcsFile
->recordMetric($stackPtr, 'Space after operator', 0);
}
else {
if (isset($tokens[$stackPtr + 2]) === true && $tokens[$stackPtr + 2]['line'] !== $tokens[$stackPtr]['line']) {
$found = 'newline';
}
else {
$found = $tokens[$stackPtr + 1]['length'];
}
$phpcsFile
->recordMetric($stackPtr, 'Space after operator', $found);
if ($found !== 1 && ($found !== 'newline' || $this->ignoreNewlines === false)) {
$error = 'Expected 1 space after "%s"; %s found';
$data = array(
$operator,
$found,
);
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'SpacingAfter', $data);
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($stackPtr + 1, ' ');
}
}
}
}
}