diff --git a/src/Ruleset.php b/src/Ruleset.php index 57e10e8464..95446e6254 100644 --- a/src/Ruleset.php +++ b/src/Ruleset.php @@ -1409,7 +1409,12 @@ public function registerSniffs($files, $restrictions, $exclusions) continue; } - if ($reflection->implementsInterface('PHP_CodeSniffer\Sniffs\Sniff') === false) { + if ($reflection->implementsInterface('PHP_CodeSniffer\\Sniffs\\Sniff') === false) { + $message = 'All sniffs must implement the PHP_CodeSniffer\\Sniffs\\Sniff interface.'.PHP_EOL; + $message .= "Interface not implemented for sniff $className.".PHP_EOL; + $message .= 'Contact the sniff author to fix the sniff.'; + $this->msgCache->add($message, MessageCollector::DEPRECATED); + // Skip classes which don't implement the register() or process() methods. if (method_exists($className, 'register') === false || method_exists($className, 'process') === false diff --git a/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php new file mode 100644 index 0000000000..39e61e385a --- /dev/null +++ b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php @@ -0,0 +1,24 @@ + + diff --git a/tests/Core/Ruleset/ProcessRulesetTest.php b/tests/Core/Ruleset/ProcessRulesetTest.php index fa704bef51..d37c031021 100644 --- a/tests/Core/Ruleset/ProcessRulesetTest.php +++ b/tests/Core/Ruleset/ProcessRulesetTest.php @@ -67,6 +67,8 @@ public function testAutoExpandSniffsDirectory() "$std.DeprecatedInvalid.InvalidDeprecationMessage" => "$sniffDir\DeprecatedInvalid\InvalidDeprecationMessageSniff", "$std.DeprecatedInvalid.InvalidDeprecationVersion" => "$sniffDir\DeprecatedInvalid\InvalidDeprecationVersionSniff", "$std.DeprecatedInvalid.InvalidRemovalVersion" => "$sniffDir\DeprecatedInvalid\InvalidRemovalVersionSniff", + "$std.MissingInterface.ValidImplements" => "$sniffDir\MissingInterface\ValidImplementsSniff", + "$std.MissingInterface.ValidImplementsViaAbstract" => "$sniffDir\MissingInterface\ValidImplementsViaAbstractSniff", "$std.SetProperty.AllowedAsDeclared" => "$sniffDir\SetProperty\AllowedAsDeclaredSniff", "$std.SetProperty.AllowedViaMagicMethod" => "$sniffDir\SetProperty\AllowedViaMagicMethodSniff", "$std.SetProperty.AllowedViaStdClass" => "$sniffDir\SetProperty\AllowedViaStdClassSniff", diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml new file mode 100644 index 0000000000..52b264f07e --- /dev/null +++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php new file mode 100644 index 0000000000..89c82c028a --- /dev/null +++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php @@ -0,0 +1,65 @@ + + * @copyright 2025 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; + +/** + * Tests deprecation of support for sniffs not implementing the PHPCS `Sniff` interface. + * + * @covers \PHP_CodeSniffer\Ruleset::registerSniffs + */ +final class RegisterSniffsMissingInterfaceTest extends TestCase +{ + + + /** + * Test that no deprecation is shown when sniffs implement the `PHP_CodeSniffer\Sniffs\Sniff` interface. + * + * @return void + */ + public function testNoNoticesForSniffsImplementingInterface() + { + // Set up the ruleset. + $standard = __DIR__.'/RegisterSniffsMissingInterfaceValidTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + + $this->expectOutputString(''); + + new Ruleset($config); + + }//end testNoNoticesForSniffsImplementingInterface() + + + /** + * Test that a deprecation notice is shown if a sniff doesn't implement the Sniff interface. + * + * @return void + */ + public function testDeprecationNoticeWhenSniffDoesntImplementInterface() + { + // Set up the ruleset. + $standard = __DIR__.'/RegisterSniffsMissingInterfaceInvalidTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + + $expected = 'DEPRECATED: All sniffs must implement the PHP_CodeSniffer\\Sniffs\\Sniff interface.'.PHP_EOL; + $expected .= 'Interface not implemented for sniff Fixtures\\TestStandard\\Sniffs\\MissingInterface\\InvalidImplementsWithoutImplementSniff.'.PHP_EOL; + $expected .= 'Contact the sniff author to fix the sniff.'.PHP_EOL.PHP_EOL; + + $this->expectOutputString($expected); + + new Ruleset($config); + + }//end testDeprecationNoticeWhenSniffDoesntImplementInterface() + + +}//end class diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml new file mode 100644 index 0000000000..39de8d4224 --- /dev/null +++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml index ab632b1959..4cfecfe79f 100644 --- a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml +++ b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml @@ -7,6 +7,7 @@ +