From 09e0820cb06714b5577f47e62ba482465c072e07 Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Mon, 23 Jun 2025 19:56:16 +0300 Subject: [PATCH 1/3] add MissedSpacesSniff.php --- src/PhpCs/FiveLab/ErrorCodes.php | 1 + .../Commenting/ProhibitedDocCommentsSniff.php | 2 +- .../Sniffs/Formatting/MissedSpacesSniff.php | 114 +++++++++++++++++ .../WhiteSpaceAroundMultilineCallSniff.php | 14 +- .../Sniffs/Namespace/NamespaceSniff.php | 1 + .../Whitespace/ManyWhitespacesSniff.php | 3 - src/PhpStan/MethodCallConsistencyRule.php | 3 + .../Formatting/MissedSpacesSniffTest.php | 120 ++++++++++++++++++ .../Resources/missed-spaces/success.php | 12 ++ .../Resources/missed-spaces/wrong.php | 23 ++++ 10 files changed, 276 insertions(+), 17 deletions(-) create mode 100644 src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php create mode 100644 tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php create mode 100644 tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/missed-spaces/success.php create mode 100644 tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/missed-spaces/wrong.php diff --git a/src/PhpCs/FiveLab/ErrorCodes.php b/src/PhpCs/FiveLab/ErrorCodes.php index c2a2f5f..9580076 100644 --- a/src/PhpCs/FiveLab/ErrorCodes.php +++ b/src/PhpCs/FiveLab/ErrorCodes.php @@ -33,4 +33,5 @@ final class ErrorCodes public const NAMESPACE_WRONG = 'NamespaceWrong'; public const ARRAYS_DOC_VECTOR = 'ArraysDocVector'; public const PHPDOC_NOT_ALLOWED = 'PhpDocNotAllowed'; + public const MISSED_SPACE = 'MissedSpace'; } diff --git a/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php b/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php index 93d3227..ae1b2dd 100644 --- a/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Commenting/ProhibitedDocCommentsSniff.php @@ -33,7 +33,7 @@ public function process(File $phpcsFile, mixed $stackPtr): void $possiblyDeclaration = $phpcsFile->findNext([ T_CLASS, T_INTERFACE, T_TRAIT, T_FUNCTION, - T_ABSTRACT, T_FINAL, T_ENUM + T_ABSTRACT, T_FINAL, T_ENUM, ], $commentToken['comment_closer'] + 1, local: true); if ($possiblyDeclaration) { diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php new file mode 100644 index 0000000..f69c22d --- /dev/null +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php @@ -0,0 +1,114 @@ +getTokens(); + $token = $tokens[$stackPtr]; + + if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { + if ($token['code'] === T_INLINE_ELSE || $token['code'] === T_INLINE_THEN) { + $this->analiseThenElse($phpcsFile, $stackPtr, true); + + return; + } + + $phpcsFile->addError( + 'Missed one space before logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + } + + if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { + if ($token['code'] === T_INLINE_THEN || $token['code'] === T_INLINE_ELSE) { + $this->analiseThenElse($phpcsFile, $stackPtr, false); + + return; + } + + $phpcsFile->addError( + 'Missed one space after logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + } + } + + private function analiseThenElse(File $phpcsFile, mixed $stackPtr, bool $before): void + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + if ($token['code'] === T_INLINE_THEN) { + if ($before) { + $phpcsFile->addError( + 'Missed one space before logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + + return; + } + + if ($tokens[$stackPtr + 1]['code'] === T_INLINE_ELSE) { + return; + } + + $phpcsFile->addError( + 'Missed one space after logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + } + + if ($token['code'] === T_INLINE_ELSE) { + if ($before) { + if ($tokens[$stackPtr - 1]['code'] === T_INLINE_THEN) { + if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { + $phpcsFile->addError( + 'Missed one space after logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + } + + return; + } + + $phpcsFile->addError( + 'Missed one space before logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + + return; + } + + $phpcsFile->addError( + 'Missed one space after logical operand.', + $stackPtr, + ErrorCodes::MISSED_SPACE + ); + } + } +} diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundMultilineCallSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundMultilineCallSniff.php index c6dc55b..dd839fc 100644 --- a/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundMultilineCallSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/WhiteSpaceAroundMultilineCallSniff.php @@ -48,12 +48,6 @@ protected function processFunctionCall(File $phpcsFile, int $stackPtr, array $pa } } - /** - * Check before multiline call - * - * @param File $phpcsFile - * @param int $stackPtr - */ private function checkBeforeCall(File $phpcsFile, int $stackPtr): void { $tokens = $phpcsFile->getTokens(); @@ -101,12 +95,6 @@ private function checkBeforeCall(File $phpcsFile, int $stackPtr): void } } - /** - * Check after multiline call - * - * @param File $phpcsFile - * @param int $closeParenthesisPtr - */ private function checkAfterCall(File $phpcsFile, int $closeParenthesisPtr): void { $tokens = $phpcsFile->getTokens(); @@ -128,7 +116,7 @@ private function checkAfterCall(File $phpcsFile, int $closeParenthesisPtr): void $possibleNextTokens = [T_CLOSE_CURLY_BRACKET, T_BREAK]; - if (!\in_array($nextToken['code'], $possibleNextTokens, true) && $diffLines < 2) { + if ($diffLines < 2 && !\in_array($nextToken['code'], $possibleNextTokens, true)) { $phpcsFile->addError( 'Must be one blank line after multiline call.', $nextTokenPtr, diff --git a/src/PhpCs/FiveLab/Sniffs/Namespace/NamespaceSniff.php b/src/PhpCs/FiveLab/Sniffs/Namespace/NamespaceSniff.php index 728884c..f46574d 100644 --- a/src/PhpCs/FiveLab/Sniffs/Namespace/NamespaceSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Namespace/NamespaceSniff.php @@ -82,6 +82,7 @@ private function getExpectedNamespace(File $phpcsFile): ?string * @param string $composerJsonPath * * @return array + * * @throws \JsonException */ private function loadComposerJson(string $composerJsonPath): array diff --git a/src/PhpCs/FiveLab/Sniffs/Whitespace/ManyWhitespacesSniff.php b/src/PhpCs/FiveLab/Sniffs/Whitespace/ManyWhitespacesSniff.php index 46cb8f8..a52d698 100644 --- a/src/PhpCs/FiveLab/Sniffs/Whitespace/ManyWhitespacesSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Whitespace/ManyWhitespacesSniff.php @@ -17,9 +17,6 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; -/** - * Check many whitespaces. - */ class ManyWhitespacesSniff implements Sniff { public function register(): array diff --git a/src/PhpStan/MethodCallConsistencyRule.php b/src/PhpStan/MethodCallConsistencyRule.php index 33e964d..013994a 100644 --- a/src/PhpStan/MethodCallConsistencyRule.php +++ b/src/PhpStan/MethodCallConsistencyRule.php @@ -62,6 +62,7 @@ public function processNode(Node $node, Scope $scope): array * @param Scope $scope * * @return list + * * @throws ShouldNotHappenException */ private function checkStaticCall(Node\Expr\StaticCall $node, Scope $scope): array @@ -96,6 +97,7 @@ private function checkStaticCall(Node\Expr\StaticCall $node, Scope $scope): arra * @param Scope $scope * * @return list + * * @throws ShouldNotHappenException */ private function checkInstanceCall(Node\Expr\MethodCall $node, Scope $scope): array @@ -130,6 +132,7 @@ private function checkInstanceCall(Node\Expr\MethodCall $node, Scope $scope): ar * @param Scope $scope * * @return list + * * @throws ShouldNotHappenException|MissingMethodFromReflectionException */ private function checkNativeMethodCall(Node\Expr\StaticCall $node, Scope $scope): array diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php new file mode 100644 index 0000000..f5c1eef --- /dev/null +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php @@ -0,0 +1,120 @@ + [ +// __DIR__.'/Resources/missed-spaces/success.php', +// ], + + 'missed' => [ + __DIR__.'/Resources/missed-spaces/wrong.php', + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 7, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 7, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 8, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 9, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 11, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 11, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 12, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 13, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 15, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 15, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 16, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 16, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 18, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 19, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 21, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 21, + ], + [ + 'message' => 'Missed one space before logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 22, + ], + [ + 'message' => 'Missed one space after logical operand.', + 'source' => 'FiveLab.Formatting.MissedSpaces.MissedSpace', + 'line' => 23, + ], + ], + + ]; + } +} diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/missed-spaces/success.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/missed-spaces/success.php new file mode 100644 index 0000000..8d42817 --- /dev/null +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/Resources/missed-spaces/success.php @@ -0,0 +1,12 @@ + Date: Mon, 23 Jun 2025 20:00:42 +0300 Subject: [PATCH 2/3] fix code style --- .../FiveLab/Sniffs/Formatting/MissedSpacesSniff.php | 9 +++++++++ .../FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php b/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php index f69c22d..e0eab14 100644 --- a/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php +++ b/src/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniff.php @@ -2,6 +2,15 @@ declare(strict_types = 1); +/* + * This file is part of the FiveLab CiRules package + * + * (c) FiveLab + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code + */ + namespace FiveLab\Component\CiRules\PhpCs\FiveLab\Sniffs\Formatting; use FiveLab\Component\CiRules\PhpCs\FiveLab\ErrorCodes; diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php index f5c1eef..ba4feda 100644 --- a/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php @@ -17,9 +17,9 @@ protected function getSniffClass(): string public static function provideDataSet(): array { return [ -// 'success' => [ -// __DIR__.'/Resources/missed-spaces/success.php', -// ], + 'success' => [ + __DIR__.'/Resources/missed-spaces/success.php', + ], 'missed' => [ __DIR__.'/Resources/missed-spaces/wrong.php', From 706e445fbddbb223231a82adf0fdf88878a680b5 Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Mon, 23 Jun 2025 20:01:59 +0300 Subject: [PATCH 3/3] fix code style --- .../FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php index ba4feda..3a218b6 100644 --- a/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php +++ b/tests/PhpCs/FiveLab/Sniffs/Formatting/MissedSpacesSniffTest.php @@ -2,6 +2,15 @@ declare(strict_types = 1); +/* + * This file is part of the FiveLab CiRules package + * + * (c) FiveLab + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code + */ + namespace FiveLab\Component\CiRules\Tests\PhpCs\FiveLab\Sniffs\Formatting; use FiveLab\Component\CiRules\PhpCs\FiveLab\Sniffs\Formatting\MissedSpacesSniff;