176 lines
4.5 KiB
PHP
176 lines
4.5 KiB
PHP
<?php declare(strict_types = 1);
|
|
|
|
namespace SlevomatCodingStandard\Sniffs\Whitespaces;
|
|
|
|
use PHP_CodeSniffer\Files\File;
|
|
use PHP_CodeSniffer\Sniffs\Sniff;
|
|
use PHP_CodeSniffer\Util\Tokens;
|
|
use SlevomatCodingStandard\Helpers\IndentationHelper;
|
|
use SlevomatCodingStandard\Helpers\ParameterHelper;
|
|
use SlevomatCodingStandard\Helpers\TokenHelper;
|
|
use function in_array;
|
|
use function preg_match_all;
|
|
use function preg_replace;
|
|
use function sprintf;
|
|
use function str_repeat;
|
|
use function str_replace;
|
|
use function strlen;
|
|
use const PREG_OFFSET_CAPTURE;
|
|
use const T_DOC_COMMENT_CLOSE_TAG;
|
|
use const T_DOC_COMMENT_OPEN_TAG;
|
|
use const T_DOC_COMMENT_STAR;
|
|
use const T_DOC_COMMENT_STRING;
|
|
use const T_DOC_COMMENT_TAG;
|
|
use const T_DOC_COMMENT_WHITESPACE;
|
|
use const T_MATCH_ARROW;
|
|
use const T_VARIABLE;
|
|
use const T_WHITESPACE;
|
|
|
|
class DuplicateSpacesSniff implements Sniff
|
|
{
|
|
|
|
public const CODE_DUPLICATE_SPACES = 'DuplicateSpaces';
|
|
|
|
/** @var bool */
|
|
public $ignoreSpacesBeforeAssignment = false;
|
|
|
|
/** @var bool */
|
|
public $ignoreSpacesInAnnotation = false;
|
|
|
|
/** @var bool */
|
|
public $ignoreSpacesInComment = false;
|
|
|
|
/** @var bool */
|
|
public $ignoreSpacesInParameters = false;
|
|
|
|
/** @var bool */
|
|
public $ignoreSpacesInMatch = false;
|
|
|
|
/**
|
|
* @return array<int, (int|string)>
|
|
*/
|
|
public function register(): array
|
|
{
|
|
return [
|
|
T_WHITESPACE,
|
|
T_DOC_COMMENT_WHITESPACE,
|
|
T_DOC_COMMENT_STRING,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
|
|
* @param int $whitespacePointer
|
|
*/
|
|
public function process(File $phpcsFile, $whitespacePointer): void
|
|
{
|
|
$tokens = $phpcsFile->getTokens();
|
|
|
|
if ($tokens[$whitespacePointer]['column'] === 1) {
|
|
return;
|
|
}
|
|
|
|
$content = $tokens[$whitespacePointer]['content'];
|
|
|
|
if ($content === $phpcsFile->eolChar) {
|
|
return;
|
|
}
|
|
|
|
if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) {
|
|
if ($this->ignoreSpacesBeforeAssignment) {
|
|
$pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1);
|
|
if (
|
|
$pointerAfter !== null
|
|
&& in_array($tokens[$pointerAfter]['code'], Tokens::$assignmentTokens, true)
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ($this->ignoreSpacesInParameters) {
|
|
$pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1);
|
|
if (
|
|
$pointerAfter !== null
|
|
&& $tokens[$pointerAfter]['code'] === T_VARIABLE
|
|
&& ParameterHelper::isParameter($phpcsFile, $pointerAfter)
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ($this->ignoreSpacesInMatch) {
|
|
$pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1);
|
|
if (
|
|
$pointerAfter !== null
|
|
&& $tokens[$pointerAfter]['code'] === T_MATCH_ARROW
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
if ($this->ignoreSpacesInComment) {
|
|
return;
|
|
}
|
|
|
|
if (
|
|
$tokens[$whitespacePointer - 1]['code'] === T_DOC_COMMENT_STAR
|
|
&& $tokens[$whitespacePointer + 1]['code'] === T_DOC_COMMENT_STRING
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if ($this->ignoreSpacesInAnnotation) {
|
|
$pointerBefore = TokenHelper::findPrevious($phpcsFile, [T_DOC_COMMENT_OPEN_TAG, T_DOC_COMMENT_TAG], $whitespacePointer - 1);
|
|
if (
|
|
$pointerBefore !== null
|
|
&& $tokens[$pointerBefore]['code'] === T_DOC_COMMENT_TAG
|
|
&& $tokens[$whitespacePointer + 1]['code'] !== T_DOC_COMMENT_CLOSE_TAG
|
|
) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
$matchResult = preg_match_all('~ {2,}~', $content, $matches, PREG_OFFSET_CAPTURE);
|
|
if ($matchResult === false || $matchResult === 0) {
|
|
return;
|
|
}
|
|
|
|
$tabWidth = $phpcsFile->config->tabWidth;
|
|
|
|
$fix = false;
|
|
foreach ($matches[0] as [$match, $offset]) {
|
|
$firstPointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $whitespacePointer - 1);
|
|
$indentation = IndentationHelper::getIndentation($phpcsFile, $firstPointerOnLine);
|
|
$indentationWithoutTabs = str_replace(
|
|
IndentationHelper::TAB_INDENT,
|
|
$tabWidth === 0 ? IndentationHelper::SPACES_INDENT : str_repeat(' ', $tabWidth),
|
|
$indentation
|
|
);
|
|
|
|
$position = $tokens[$whitespacePointer]['column'] + $offset - strlen($indentation) + strlen($indentationWithoutTabs);
|
|
|
|
$fixable = $phpcsFile->addFixableError(
|
|
sprintf('Duplicate spaces at position %d.', $position),
|
|
$whitespacePointer,
|
|
self::CODE_DUPLICATE_SPACES
|
|
);
|
|
|
|
if ($fixable) {
|
|
$fix = true;
|
|
}
|
|
}
|
|
|
|
if (!$fix) {
|
|
return;
|
|
}
|
|
|
|
$phpcsFile->fixer->beginChangeset();
|
|
|
|
$phpcsFile->fixer->replaceToken($whitespacePointer, preg_replace('~ {2,}~', ' ', $content));
|
|
|
|
$phpcsFile->fixer->endChangeset();
|
|
}
|
|
|
|
}
|