diff --git a/README.md b/README.md index b44b78e73..46fadddc8 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ Slevomat Coding Standard for [PHP_CodeSniffer](https://github.com/squizlabs/PHP_ - [SlevomatCodingStandard.Functions.DisallowTrailingCommaInClosureUse](doc/functions.md#slevomatcodingstandardfunctionsdisallowtrailingcommainclosureuse-) 🔧 - [SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration](doc/functions.md#slevomatcodingstandardfunctionsdisallowtrailingcommaindeclaration-) 🔧 - [SlevomatCodingStandard.Functions.FunctionLength](doc/functions.md#slevomatcodingstandardfunctionsfunctionlength) + - [SlevomatCodingStandard.Functions.NamedArgumentSpacing](doc/functions.md#slevomatcodingstandardfunctionsnamedargumentspacing-) 🔧 - [SlevomatCodingStandard.Functions.RequireArrowFunction](doc/functions.md#slevomatcodingstandardfunctionsrequirearrowfunction-) 🔧 - [SlevomatCodingStandard.Functions.RequireMultiLineCall](doc/functions.md#slevomatcodingstandardfunctionsrequiremultilinecall-) 🔧 - [SlevomatCodingStandard.Functions.RequireSingleLineCall](doc/functions.md#slevomatcodingstandardfunctionsrequiresinglelinecall-) 🔧 diff --git a/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php b/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php new file mode 100644 index 000000000..5ad5c821c --- /dev/null +++ b/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php @@ -0,0 +1,79 @@ + + */ + public function register(): array + { + return [ + T_PARAM_NAME, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $colonPointer */ + $colonPointer = TokenHelper::findNext($phpcsFile, T_COLON, $pointer + 1); + + $parameterName = $tokens[$pointer]['content']; + + if ($colonPointer !== $pointer + 1) { + $fix = $phpcsFile->addFixableError( + sprintf('There must be no whitespace between named argument "%s" and colon.', $parameterName), + $colonPointer, + self::CODE_WHITESPACE_BEFORE_COLOR + ); + if ($fix) { + $phpcsFile->fixer->replaceToken($colonPointer - 1, ''); + } + } + + $whitespacePointer = $colonPointer + 1; + + if ( + $tokens[$whitespacePointer]['code'] === T_WHITESPACE + && $tokens[$whitespacePointer]['content'] === ' ' + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('There must be exactly one space after colon in named argument "%s".', $parameterName), + $colonPointer, + self::CODE_NO_WHITESPACE_AFTER_COLON + ); + + if (!$fix) { + return; + } + + if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($whitespacePointer, ' '); + } else { + $phpcsFile->fixer->addContent($colonPointer, ' '); + } + } + +} diff --git a/build/phpcs.xml b/build/phpcs.xml index b999b8aa1..929551e3f 100644 --- a/build/phpcs.xml +++ b/build/phpcs.xml @@ -370,6 +370,7 @@ + diff --git a/doc/functions.md b/doc/functions.md index 5ea350d67..2766552c5 100644 --- a/doc/functions.md +++ b/doc/functions.md @@ -57,6 +57,10 @@ Sniff provides the following settings: This sniff disallows usage of named arguments. +#### SlevomatCodingStandard.Functions.NamedArgumentSpacing 🔧 + +Checks spacing in named argument. + #### SlevomatCodingStandard.Functions.DisallowTrailingCommaInCall 🔧 This sniff disallows trailing commas in multi-line calls. diff --git a/tests/Sniffs/Functions/NamedArgumentSpacingSniffTest.php b/tests/Sniffs/Functions/NamedArgumentSpacingSniffTest.php new file mode 100644 index 000000000..8b479437a --- /dev/null +++ b/tests/Sniffs/Functions/NamedArgumentSpacingSniffTest.php @@ -0,0 +1,44 @@ +getErrorCount()); + + self::assertSniffError( + $report, + 3, + NamedArgumentSpacingSniff::CODE_WHITESPACE_BEFORE_COLOR, + 'There must be no whitespace between named argument "search" and colon.' + ); + self::assertSniffError( + $report, + 4, + NamedArgumentSpacingSniff::CODE_NO_WHITESPACE_AFTER_COLON, + 'There must be exactly one space after colon in named argument "search".' + ); + self::assertSniffError( + $report, + 4, + NamedArgumentSpacingSniff::CODE_NO_WHITESPACE_AFTER_COLON, + 'There must be exactly one space after colon in named argument "subject".' + ); + + self::assertAllFixedInFile($report); + } + +} diff --git a/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.fixed.php b/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.fixed.php new file mode 100644 index 000000000..2113bfed2 --- /dev/null +++ b/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.fixed.php @@ -0,0 +1,4 @@ += 8.0 + +str_replace(search: 'foo', replace: 'bar', subject: 'foo lol'); +str_replace(search: 'foo', replace: 'bar', subject: 'foo lol'); diff --git a/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.php b/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.php new file mode 100644 index 000000000..6eb7f2e14 --- /dev/null +++ b/tests/Sniffs/Functions/data/namedArgumentSpacingErrors.php @@ -0,0 +1,4 @@ += 8.0 + +str_replace(search : 'foo', replace: 'bar', subject: 'foo lol'); +str_replace(search:'foo', replace: 'bar', subject: 'foo lol'); diff --git a/tests/Sniffs/Functions/data/namedArgumentSpacingNoErrors.php b/tests/Sniffs/Functions/data/namedArgumentSpacingNoErrors.php new file mode 100644 index 000000000..741830802 --- /dev/null +++ b/tests/Sniffs/Functions/data/namedArgumentSpacingNoErrors.php @@ -0,0 +1,5 @@ += 8.0 + +str_replace(search: 'foo', replace: 'bar', subject: 'foo lol'); // space before + missing space + +str_replace('foo', 'bar', 'foo');