Skip to content

Ruleset: hard deprecate support for sniffs not implementing the Sniff interface #891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/Ruleset.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* Test fixture.
*
* @see \PHP_CodeSniffer\Tests\Core\Ruleset\RegisterSniffsMissingInterfaceTest
*/

namespace Fixtures\TestStandard\Sniffs\MissingInterface;

use PHP_CodeSniffer\Files\File;

final class InvalidImplementsWithoutImplementSniff
{

public function register()
{
return [T_OPEN_TAG];
}

public function process(File $phpcsFile, $stackPtr)
{
// Do something.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* Test fixture.
*
* @see \PHP_CodeSniffer\Tests\Core\Ruleset\RegisterSniffsMissingInterfaceTest
*/

namespace Fixtures\TestStandard\Sniffs\MissingInterface;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;

final class ValidImplementsSniff implements Sniff
{

public function register()
{
return [T_OPEN_TAG];
}

public function process(File $phpcsFile, $stackPtr)
{
// Do something.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* Test fixture.
*
* @see \PHP_CodeSniffer\Tests\Core\Ruleset\RegisterSniffsMissingInterfaceTest
*/

namespace Fixtures\TestStandard\Sniffs\MissingInterface;

use PHP_CodeSniffer\Sniffs\AbstractArraySniff;

final class ValidImplementsViaAbstractSniff extends AbstractArraySniff
{

protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices)
{
// Do something.
}

protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices)
{
// Do something.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<rule ref="TestStandard">
<exclude name="TestStandard.InvalidSniffs"/>
<exclude name="TestStandard.InvalidSniffError"/>
<exclude name="TestStandard.MissingInterface.InvalidImplementsWithoutImplement"/>
</rule>

</ruleset>
2 changes: 2 additions & 0 deletions tests/Core/Ruleset/ProcessRulesetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="RegisterSniffsMissingInterfaceTest" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/PHPCSStandards/PHP_CodeSniffer/master/phpcs.xsd">

<config name="installed_paths" value="./tests/Core/Ruleset/Fixtures/TestStandard/"/>

<rule ref="TestStandard.MissingInterface"/>

</ruleset>
65 changes: 65 additions & 0 deletions tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
/**
* Tests deprecation of support for sniffs not implementing the PHPCS `Sniff` interface.
*
* @author Juliette Reinders Folmer <[email protected]>
* @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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="RegisterSniffsMissingInterfaceTest" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/PHPCSStandards/PHP_CodeSniffer/master/phpcs.xsd">

<config name="installed_paths" value="./tests/Core/Ruleset/Fixtures/TestStandard/"/>

<rule ref="TestStandard.MissingInterface.ValidImplements"/>
<rule ref="TestStandard.MissingInterface.ValidImplementsViaAbstract"/>

</ruleset>
1 change: 1 addition & 0 deletions tests/Core/Ruleset/ShowSniffDeprecationsTest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<exclude name="TestStandard.DeprecatedInvalid"/>
<exclude name="TestStandard.InvalidSniffs"/>
<exclude name="TestStandard.InvalidSniffError"/>
<exclude name="TestStandard.MissingInterface"/>
</rule>

</ruleset>