From 57ba46f900dc5571d560cf78dc84a8f822b18528 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 7 Feb 2025 03:39:50 +0100 Subject: [PATCH] Ruleset: hard deprecate support for sniffs not following the naming conventions The new [About Standards for PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/About-Standards-for-PHP_CodeSniffer) wiki page outlines exactly what the naming conventions are. This PR adds a new Ruleset deprecation notice for when sniffs are encountered which do not follow these conventions. Support for sniffs not following the naming conventions will be removed in PHPCS 4.0. Includes tests. Includes removing two invalid sniffs from the `ExpandSniffDirectoryTest`. These type of sniffs, which don't comply with the PHPCS naming conventions, are now covered via the new tests. Related to 689 --- src/Ruleset.php | 13 +++ .../Core/Ruleset/ExpandSniffDirectoryTest.php | 15 +--- .../Sniffs/Category/Sniff.php | 24 ++++++ .../Category/SubDir/TooDeeplyNestedSniff.php | 24 ++++++ .../Sniffs/MissingCategoryDirSniff.php | 24 ++++++ .../Sniffs/NoNamespaceSniff.php | 22 +++++ .../Sniffs/PartialNamespaceSniff.php | 24 ++++++ .../Sniffs/CategoryCalledSniffsSniff.php | 24 ++++++ .../IncorrectLevelShouldStillBeFoundSniff.php | 12 --- .../IncorrectLevelShouldStillBeFoundSniff.php | 12 --- ...ateTokenListenersNamingConventionsTest.php | 82 +++++++++++++++++++ ...ateTokenListenersNamingConventionsTest.xml | 24 ++++++ 12 files changed, 263 insertions(+), 37 deletions(-) create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Category/Sniff.php create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Category/SubDir/TooDeeplyNestedSniff.php create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/MissingCategoryDirSniff.php create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/NoNamespaceSniff.php create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/PartialNamespaceSniff.php create mode 100644 tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Sniffs/CategoryCalledSniffsSniff.php delete mode 100644 tests/Core/Ruleset/Fixtures/DirectoryExpansion/.hiddenAbove/src/MyStandard/Sniffs/CategoryA/Subdir/IncorrectLevelShouldStillBeFoundSniff.php delete mode 100644 tests/Core/Ruleset/Fixtures/DirectoryExpansion/.hiddenAbove/src/MyStandard/Sniffs/IncorrectLevelShouldStillBeFoundSniff.php create mode 100644 tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.php create mode 100644 tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.xml diff --git a/src/Ruleset.php b/src/Ruleset.php index b6279bf9f3..ded66b4c9b 100644 --- a/src/Ruleset.php +++ b/src/Ruleset.php @@ -1455,6 +1455,19 @@ public function populateTokenListeners() $this->sniffs[$sniffClass] = new $sniffClass(); $sniffCode = Common::getSniffCode($sniffClass); + + if (substr($sniffCode, 0, 1) === '.' + || substr($sniffCode, -1) === '.' + || strpos($sniffCode, '..') !== false + || preg_match('`(^|\.)Sniffs\.`', $sniffCode) === 1 + || preg_match('`[^\s\.-]+\\\\Sniffs\\\\[^\s\.-]+\\\\[^\s\.-]+Sniff`', $sniffClass) !== 1 + ) { + $message = "The sniff $sniffClass does not comply with the PHP_CodeSniffer naming conventions."; + $message .= ' This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $message .= 'Contact the sniff author to fix the sniff.'; + $this->msgCache->add($message, MessageCollector::DEPRECATED); + } + $this->sniffCodes[$sniffCode] = $sniffClass; if ($this->sniffs[$sniffClass] instanceof DeprecatedSniff) { diff --git a/tests/Core/Ruleset/ExpandSniffDirectoryTest.php b/tests/Core/Ruleset/ExpandSniffDirectoryTest.php index 8f7f4f93f6..ddd3a51489 100644 --- a/tests/Core/Ruleset/ExpandSniffDirectoryTest.php +++ b/tests/Core/Ruleset/ExpandSniffDirectoryTest.php @@ -49,20 +49,9 @@ public function testExpandSniffDirectory() $this->assertNotFalse($expectedPathToRuleset, 'Ruleset file could not be found'); $this->assertContains($expectedPathToRuleset, $ruleset->paths, 'Ruleset file not included in the "seen ruleset paths"'); - /* - * Take note: the expectation includes some "undesirables" related to the convoluted directory structure - * in the "standard" used as a test fixture. - * - * That is okay as (for now) non-standard directory layouts are supported. - * - * This test is not about the standard directory layout. - */ - $expectedSniffCodes = [ - '.Sniffs.IncorrectLevelShouldStillBeFound' => 'MyStandard\\Sniffs\\IncorrectLevelShouldStillBeFoundSniff', - 'MyStandard.CategoryA.FindMe' => 'MyStandard\\Sniffs\\CategoryA\\FindMeSniff', - 'MyStandard.CategoryB.FindMe' => 'MyStandard\\Sniffs\\CategoryB\\FindMeSniff', - 'Sniffs.SubDir.IncorrectLevelShouldStillBeFound' => 'MyStandard\\Sniffs\\CategoryA\\SubDir\\IncorrectLevelShouldStillBeFoundSniff', + 'MyStandard.CategoryA.FindMe' => 'MyStandard\\Sniffs\\CategoryA\\FindMeSniff', + 'MyStandard.CategoryB.FindMe' => 'MyStandard\\Sniffs\\CategoryB\\FindMeSniff', ]; // Sort the value to make the tests stable as different OSes will read directories diff --git a/tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Category/Sniff.php b/tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Category/Sniff.php new file mode 100644 index 0000000000..9da190d175 --- /dev/null +++ b/tests/Core/Ruleset/Fixtures/BrokenNamingConventions/Sniffs/Category/Sniff.php @@ -0,0 +1,24 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Test handling of sniffs not following the PHPCS naming conventions in the Ruleset::populateTokenListeners() method. + * + * @covers \PHP_CodeSniffer\Ruleset::populateTokenListeners + */ +final class PopulateTokenListenersNamingConventionsTest extends TestCase +{ + + + /** + * Verify a warning is shown for sniffs not complying with the PHPCS naming conventions. + * + * Including sniffs which do not comply with the PHPCS naming conventions is soft deprecated since + * PHPCS 3.12.0, hard deprecated since PHPCS 3.13.0 and support will be removed in PHPCS 4.0.0. + * + * @return void + */ + public function testBrokenNamingConventions() + { + // Set up the ruleset. + $standard = __DIR__.'/PopulateTokenListenersNamingConventionsTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + // The "Generic.PHP.BacktickOperator" sniff is the only valid sniff. + $expectedSniffCodes = [ + '..NoNamespace' => 'NoNamespaceSniff', + '.Sniffs.MissingCategoryDir' => 'BrokenNamingConventions\\Sniffs\\MissingCategoryDirSniff', + '.Sniffs.PartialNamespace' => 'Sniffs\\PartialNamespaceSniff', + 'BrokenNamingConventions.Category.' => 'BrokenNamingConventions\\Sniffs\\Category\\Sniff', + 'BrokenNamingConventions.Sniffs.CategoryCalledSniffs' => 'BrokenNamingConventions\\Sniffs\\Sniffs\\CategoryCalledSniffsSniff', + 'Generic.PHP.BacktickOperator' => 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\PHP\\BacktickOperatorSniff', + 'Sniffs.SubDir.TooDeeplyNested' => 'BrokenNamingConventions\\Sniffs\\Category\\SubDir\\TooDeeplyNestedSniff', + ]; + + // Sort the value to make the tests stable as different OSes will read directories + // in a different order and the order is not relevant for these tests. Just the values. + $actual = $ruleset->sniffCodes; + ksort($actual); + + $this->assertSame($expectedSniffCodes, $actual, 'Registered sniffs do not match expectation'); + + $expectedMessage = 'DEPRECATED: The sniff BrokenNamingConventions\\Sniffs\\MissingCategoryDirSniff does not comply'; + $expectedMessage .= ' with the PHP_CodeSniffer naming conventions. This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL; + $expectedMessage .= 'DEPRECATED: The sniff NoNamespaceSniff does not comply with the PHP_CodeSniffer naming conventions.'; + $expectedMessage .= ' This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL; + $expectedMessage .= 'DEPRECATED: The sniff Sniffs\\PartialNamespaceSniff does not comply with the PHP_CodeSniffer naming conventions.'; + $expectedMessage .= ' This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL; + $expectedMessage .= 'DEPRECATED: The sniff BrokenNamingConventions\\Sniffs\\Category\\Sniff does not comply'; + $expectedMessage .= ' with the PHP_CodeSniffer naming conventions. This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL; + $expectedMessage .= 'DEPRECATED: The sniff BrokenNamingConventions\\Sniffs\\Sniffs\\CategoryCalledSniffsSniff does not'; + $expectedMessage .= ' comply with the PHP_CodeSniffer naming conventions. This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL; + $expectedMessage .= 'DEPRECATED: The sniff BrokenNamingConventions\\Sniffs\\Category\\SubDir\\TooDeeplyNestedSniff'; + $expectedMessage .= ' does not comply with the PHP_CodeSniffer naming conventions. This will no longer be supported in PHPCS 4.0.'.PHP_EOL; + $expectedMessage .= 'Contact the sniff author to fix the sniff.'.PHP_EOL.PHP_EOL; + + $this->expectOutputString($expectedMessage); + + }//end testBrokenNamingConventions() + + +}//end class diff --git a/tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.xml b/tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.xml new file mode 100644 index 0000000000..4446c0dce8 --- /dev/null +++ b/tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + +