From d3cdf9c613d1336d77a94f4ac7a5d0013ba3a0ff Mon Sep 17 00:00:00 2001 From: jrfnl Date: Sun, 21 Sep 2025 02:14:11 +0200 Subject: [PATCH] Bring back whitespace tolerance in selective `phpcs:ignore` comments To selectively ignore /disable/enable standards, sniff categories, sniffs or error codes, the `phpcs:ignore`, `phpcs:disable` and `phpcs:enable` annotations take a comma-separated list of rule references and allow for an optional `-- comment` at the end of the annotation. While not strictly speaking "officially supported", the comma-separated list was whitespace tolerant in PHPCS 3.x. This was unintentionally broken in PR 123, but only for the `phpcs:ignore` syntax. The `phpcs:disable`/`phpcs:enable` annotations were not affected. This commit fixes this bug and brings back whitespace tolerance in the comma-separated list of rule references for `phpcs:ignore`. It also adds a set of tests for all three types of annotations to safeguard this. The addition of these tests effectively means that this whitespace tolerance is now officially supported. Fixes 1277 --- src/Tokenizers/Tokenizer.php | 3 +- tests/Core/ErrorSuppressionTest.php | 128 +++++++++++++++++++++++----- 2 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/Tokenizers/Tokenizer.php b/src/Tokenizers/Tokenizer.php index 07a1f5065f..5ccd3dd53a 100644 --- a/src/Tokenizers/Tokenizer.php +++ b/src/Tokenizers/Tokenizer.php @@ -447,7 +447,8 @@ private function createPositionMap() $lineIgnoring = IgnoreList::getNewInstanceFrom($ignoring); foreach ($parts as $sniffCode) { - $ignoreRules[trim($sniffCode)] = true; + $sniffCode = trim($sniffCode); + $ignoreRules[$sniffCode] = true; $lineIgnoring->set($sniffCode, true); } } diff --git a/tests/Core/ErrorSuppressionTest.php b/tests/Core/ErrorSuppressionTest.php index cfb847a4a7..267bd12c30 100644 --- a/tests/Core/ErrorSuppressionTest.php +++ b/tests/Core/ErrorSuppressionTest.php @@ -746,59 +746,65 @@ public static function dataDisableSelected() { return [ // Single sniff. - 'disable: single sniff' => [ + 'disable: single sniff' => [ 'before' => '// phpcs:disable Generic.Commenting.Todo', 'expectedErrors' => 1, ], - 'disable: single sniff with reason' => [ + 'disable: single sniff with reason' => [ 'before' => '# phpcs:disable Generic.Commenting.Todo -- for reasons', 'expectedErrors' => 1, ], - 'disable: single sniff, docblock' => [ + 'disable: single sniff, docblock' => [ 'before' => "/**\n * phpcs:disable Generic.Commenting.Todo\n */ ", 'expectedErrors' => 1, ], - 'disable: single sniff, docblock, with @' => [ + 'disable: single sniff, docblock, with @' => [ 'before' => "/**\n * @phpcs:disable Generic.Commenting.Todo\n */ ", 'expectedErrors' => 1, ], // Multiple sniffs. - 'disable: multiple sniffs in one comment' => [ + 'disable: multiple sniffs in one comment' => [ 'before' => '// phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', ], - 'disable: multiple sniff in multiple comments' => [ + 'disable: multiple sniffs in one comment with superfluous space after comma' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo, Generic.PHP.LowerCaseConstant', + ], + 'disable: multiple sniff in multiple comments' => [ 'before' => "// phpcs:disable Generic.Commenting.Todo\n// phpcs:disable Generic.PHP.LowerCaseConstant", ], // Selectiveness variations. - 'disable: complete category' => [ + 'disable: complete category' => [ 'before' => '// phpcs:disable Generic.Commenting', 'expectedErrors' => 1, ], - 'disable: whole standard' => [ + 'disable: whole standard' => [ 'before' => '// phpcs:disable Generic', ], - 'disable: single errorcode' => [ + 'disable: single errorcode' => [ 'before' => '# @phpcs:disable Generic.Commenting.Todo.TaskFound', 'expectedErrors' => 1, ], - 'disable: single errorcode and a category' => [ + 'disable: single errorcode and a category' => [ 'before' => '// phpcs:disable Generic.PHP.LowerCaseConstant.Found,Generic.Commenting', ], + 'disable: single errorcode and a category with superfluous space after comma' => [ + 'before' => '// phpcs:disable Generic.PHP.LowerCaseConstant.Found, Generic.Commenting', + ], // Wrong category/sniff/code. - 'disable: wrong error code and category' => [ + 'disable: wrong error code and category' => [ 'before' => "/**\n * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments\n */ ", 'expectedErrors' => 1, 'expectedWarnings' => 1, ], - 'disable: wrong category, docblock' => [ + 'disable: wrong category, docblock' => [ 'before' => "/**\n * phpcs:disable Generic.Files\n */ ", 'expectedErrors' => 1, 'expectedWarnings' => 1, ], - 'disable: wrong category, docblock, with @' => [ + 'disable: wrong category, docblock, with @' => [ 'before' => "/**\n * @phpcs:disable Generic.Files\n */ ", 'expectedErrors' => 1, 'expectedWarnings' => 1, @@ -876,6 +882,17 @@ public static function dataEnableSelected() 'expectedErrors' => 1, 'expectedWarnings' => 1, ], + 'disable/enable: multiple sniffs with superfluous space after comma' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo, Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo, Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], 'disable: multiple sniffs; enable: one' => [ 'code' => ' # phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant @@ -1028,6 +1045,54 @@ public static function dataEnableSelected() 'expectedErrors' => 0, 'expectedWarnings' => 0, ], + 'disable: two sniffs in one go; enable: both sniffs; ignore: one of those sniffs' => [ + 'code' => ' + // phpcs:disable Generic.PHP.LowerCaseConstant,Generic.Commenting.Todo + //TODO: write some code + $var = TRUE; + // phpcs:enable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + + $var = FALSE; // phpcs:ignore Generic.PHP.LowerCaseConstant + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + 'disable: two sniffs in one go; enable: one sniff; ignore: enabled sniff' => [ + 'code' => ' + // phpcs:disable Generic.PHP.LowerCaseConstant, Generic.Commenting.Todo + //TODO: write some code + $var = TRUE; + // phpcs:enable Generic.PHP.LowerCaseConstant + + $var = FALSE; // phpcs:ignore Generic.PHP.LowerCaseConstant + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + 'disable: two sniffs in one go; enable: one sniff; ignore: category' => [ + 'code' => ' + // phpcs:disable Generic.PHP.LowerCaseConstant,Generic.Commenting.Todo + //TODO: write some code + $var = TRUE; + // phpcs:enable Generic.PHP.LowerCaseConstant + + $var = FALSE; // phpcs:ignore Generic.PHP + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + 'disable: two sniffs in one go; enable: category; ignore: sniff in category' => [ + 'code' => ' + // phpcs:disable Generic.PHP.LowerCaseConstant, Generic.Commenting.Todo + //TODO: write some code + $var = TRUE; + // phpcs:enable Generic.PHP + + $var = FALSE; // phpcs:ignore Generic.PHP.LowerCaseConstant + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], 'disable: standard; enable: category in standard; disable: sniff in category' => [ 'code' => ' // phpcs:disable Generic @@ -1106,34 +1171,49 @@ public function testIgnoreSelected($before, $expectedErrors, $expectedWarnings) public static function dataIgnoreSelected() { return [ - 'no suppression' => [ + 'no suppression' => [ 'before' => '', 'expectedErrors' => 2, 'expectedWarnings' => 2, ], // With suppression. - 'ignore: single sniff' => [ + 'ignore: single sniff' => [ 'before' => '// phpcs:ignore Generic.Commenting.Todo', 'expectedErrors' => 2, 'expectedWarnings' => 1, ], - 'ignore: multiple sniffs' => [ + 'ignore: multiple sniffs' => [ 'before' => '// phpcs:ignore Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', 'expectedErrors' => 1, 'expectedWarnings' => 1, ], - 'disable: single sniff; ignore: single sniff' => [ + 'ignore: multiple sniffs with superfluous space after comma' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo , Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'ignore: one sniff, one category with superfluous space after comma' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo, Generic.PHP', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'ignore: one category, one error code with superfluous space after comma' => [ + 'before' => '// phpcs:ignore Generic.Commenting, Generic.PHP.LowerCaseConstant.Found', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; ignore: single sniff' => [ 'before' => "// phpcs:disable Generic.Commenting.Todo\n// phpcs:ignore Generic.PHP.LowerCaseConstant", 'expectedErrors' => 1, 'expectedWarnings' => 0, ], - 'ignore: category of sniffs' => [ + 'ignore: category of sniffs' => [ 'before' => '# phpcs:ignore Generic.Commenting', 'expectedErrors' => 2, 'expectedWarnings' => 1, ], - 'ignore: whole standard' => [ + 'ignore: whole standard' => [ 'before' => '// phpcs:ignore Generic', 'expectedErrors' => 1, 'expectedWarnings' => 1, @@ -1228,6 +1308,16 @@ public static function dataCommenting() 'expectedErrors' => 2, 'expectedWarnings' => 1, ], + 'ignore: multi sniff, line above and trailing - with comment and superfluous whitespace' => [ + 'code' => ' + // phpcs:ignore Generic.Commenting.Todo , Generic.PHP.LowerCaseConstant.Found -- Because reasons + $var = FALSE; //TODO: write some code + $var = FALSE; // phpcs:ignore Generic.Commenting.Todo , Generic.PHP.LowerCaseConstant.Found --Because reasons + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], 'enable before disable, sniff not in standard' => [ 'code' => ' // phpcs:enable Generic.PHP.NoSilencedErrors -- Because reasons