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 @@ + + + + + + + + + + + + + + + + + + + + +