-
Notifications
You must be signed in to change notification settings - Fork 51
show the idea of new sniff rule (force spaces after =)
#117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
show the idea of new sniff rule (force spaces after =)
#117
Conversation
|
Idea looks OK to me - is there no existing rule handling this? |
|
@Ocramius, At least I haven't found one. Searched in squizlabs and slevomat rules |
|
Closing/reopening to trigger CI |
|
@alcaeus notice that there is no rule for that yet |
I know that - I was trying to fix the GitHub issue where it didn't trigger a travis-ci build at all. 😉 Reason is simple: I would think that the indentation sniffs should cover this case already. |
=)
|
As @jrfnl suggested here squizlabs/PHP_CodeSniffer#2425 , we can use |
|
@vladyslavstartsev I've built this for the CS in my current company, maybe we can use it as inspiration (it removes all spaces before and after operators, not exactly what we want but can be tweaked): <?php
declare(strict_types=1);
namespace Castor\CodingStandard\Sniffs\Operators;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff as SquizOperatorSpacingSniff;
use PHP_CodeSniffer\Util\Tokens;
use const T_COMMENT;
use const T_INLINE_ELSE;
use const T_INLINE_THEN;
use const T_INSTANCEOF;
use const T_STRING_CONCAT;
use const T_WHITESPACE;
use function array_merge;
use function array_unique;
use function in_array;
use function strlen;
final class OperatorSpacingSniff extends SquizOperatorSpacingSniff
{
private const MESSAGE_BEFORE = 'Expected exactly 1 space before "%s"; %d found';
private const MESSAGE_AFTER = 'Expected exactly 1 space after "%s"; %d found';
/**
* {@inheritdoc}
*/
public function register(): array
{
return array_unique(
array_merge(
Tokens::$comparisonTokens,
Tokens::$operators,
Tokens::$assignmentTokens,
Tokens::$booleanOperators,
[
T_INLINE_THEN,
T_INLINE_ELSE,
T_STRING_CONCAT,
T_INSTANCEOF,
]
)
);
}
/**
* {@inheritdoc}
*/
public function process(File $phpcsFile, $pointer): void
{
if (! $this->isOperator($phpcsFile, $pointer)) {
return;
}
$tokens = $phpcsFile->getTokens();
$this->ensureOneSpaceBeforeOperator($phpcsFile, $pointer, $tokens);
$this->ensureOneSpaceAfterOperator($phpcsFile, $pointer, $tokens);
}
/**
* @param mixed[] $tokens
*/
private function ensureOneSpaceBeforeOperator(File $file, int $pointer, array $tokens): void
{
if (! $this->shouldValidateBefore($pointer, $tokens)) {
return;
}
$numberOfSpaces = $this->numberOfSpaces($tokens[$pointer - 1]);
if ($numberOfSpaces === 1 || ! $this->recordErrorBefore($file, $pointer, $tokens[$pointer], $numberOfSpaces)) {
return;
}
if ($numberOfSpaces === 0) {
$file->fixer->addContentBefore($pointer, ' ');
return;
}
$file->fixer->replaceToken($pointer - 1, ' ');
}
/**
* @param mixed[] $token
*/
private function recordErrorBefore(File $file, int $pointer, array $token, int $numberOfSpaces): bool
{
return $file->addFixableError(
self::MESSAGE_BEFORE,
$pointer,
'NoSpaceBefore',
[$token['content'], $numberOfSpaces]
);
}
/**
* @param mixed[] $tokens
*/
private function shouldValidateBefore(int $pointer, array $tokens): bool
{
$currentToken = $tokens[$pointer];
$previousToken = $tokens[$pointer - 1];
if ($currentToken['code'] === T_INLINE_ELSE && $previousToken['code'] === T_INLINE_THEN) {
return false;
}
if ($previousToken['code'] === T_COMMENT && $previousToken['line'] < $currentToken['line']) {
return false;
}
return ! in_array($currentToken['code'], Tokens::$booleanOperators, true)
|| $currentToken['line'] === $tokens[$pointer - 2]['line'];
}
/**
* @param mixed[] $tokens
*/
private function ensureOneSpaceAfterOperator(File $file, int $pointer, array $tokens): void
{
if (! $this->shouldValidateAfter($pointer, $tokens)) {
return;
}
$numberOfSpaces = $this->numberOfSpaces($tokens[$pointer + 1]);
if ($numberOfSpaces === 1 || ! $this->recordErrorAfter($file, $pointer, $tokens[$pointer], $numberOfSpaces)) {
return;
}
if ($numberOfSpaces === 0) {
$file->fixer->addContent($pointer, ' ');
return;
}
$file->fixer->replaceToken($pointer + 1, ' ');
}
/**
* @param mixed[] $tokens
*/
private function shouldValidateAfter(int $pointer, array $tokens): bool
{
if (! isset($tokens[$pointer + 1])) {
return false;
}
return $tokens[$pointer]['code'] !== T_INLINE_THEN || $tokens[$pointer + 1]['code'] !== T_INLINE_ELSE;
}
/**
* @param mixed[] $token
*/
private function recordErrorAfter(File $file, int $pointer, array $token, int $numberOfSpaces): bool
{
return $file->addFixableError(
self::MESSAGE_AFTER,
$pointer,
'NoSpaceAfter',
[$token['content'], $numberOfSpaces]
);
}
/**
* @param mixed[] $token
*/
private function numberOfSpaces(array $token): int
{
if ($token['code'] !== T_WHITESPACE) {
return 0;
}
return strlen($token['content']);
}
} |
|
@lcobucci I like your idea. But I thought that coding standards will not write own, but use existing one. |
|
The coding-standard can also have its own written sniffs. |
|
so, should I put the code that @lcobucci gave into the repo? |
|
@vladyslavstartsev after some modification, sure. |
|
@vladyslavstartsev What about these suggestions? |
|
@carusogabriel LGTM, sorry for not answering for a long time (currently busy a little bit) |
|
Ok, I've got some time to implement this rule 🙂 @Ocramius @alcaeus @lcobucci @SenseException by the way, what about forcing not only
|
|
@vladyslavstartsev could you rebase so we can see if the build passes? Can't vote on it for approval otherwise |
|
@Ocramius done! (forgot about that, sorry) |
|
Trying to get Travis work on this... |
|
I think it's borked: probably best to open a new PR, @vladyslavstartsev :-\ |
|
Closing here, will re-open a new PR |
I haven't yet found the rule that will help with that (since
MultipleStatementAlignmentSniffdoesn't work here)This PR/issue comes from this #103 (comment)