Skip to content
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

Ruleset: hard deprecate support for sniffs not following the naming conventions #892

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
13 changes: 13 additions & 0 deletions src/Ruleset.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
15 changes: 2 additions & 13 deletions tests/Core/Ruleset/ExpandSniffDirectoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* Test fixture.
*
* @see \PHP_CodeSniffer\Tests\Core\RulesetPopulateTokenListenersNamingConventionsTest
*/

namespace BrokenNamingConventions\Sniffs\Category;

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

final class Sniff implements PHPCS_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\RulesetPopulateTokenListenersNamingConventionsTest
*/

namespace BrokenNamingConventions\Sniffs\Category\SubDir;

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

final class TooDeeplyNestedSniff 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\RulesetPopulateTokenListenersNamingConventionsTest
*/

namespace BrokenNamingConventions\Sniffs;

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

final class MissingCategoryDirSniff 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,22 @@
<?php
/**
* Test fixture.
*
* @see \PHP_CodeSniffer\Tests\Core\Ruleset\PopulateTokenListenersNamingConventionsTest
*/

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

final class NoNamespaceSniff 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\PopulateTokenListenersNamingConventionsTest
*/

namespace Sniffs;

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

final class PartialNamespaceSniff 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\RulesetPopulateTokenListenersNamingConventionsTest
*/

namespace BrokenNamingConventions\Sniffs\Sniffs;

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

final class CategoryCalledSniffsSniff implements Sniff
{
public function register()
{
return [T_OPEN_TAG];
}

public function process(File $phpcsFile, $stackPtr)
{
// Do something.
}
}

This file was deleted.

This file was deleted.

82 changes: 82 additions & 0 deletions tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* Test the Ruleset::expandSniffDirectory() method.
*
* @author Juliette Reinders Folmer <[email protected]>
* @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
24 changes: 24 additions & 0 deletions tests/Core/Ruleset/PopulateTokenListenersNamingConventionsTest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PopulateTokenListenersNamingConventionsTest" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/PHPCSStandards/PHP_CodeSniffer/master/phpcs.xsd">

<!--
These sniff files are not in an installed standard, there is not even a ruleset.xml file for the "standard".
Each of these sniff files breaks one of the naming convention rules.
-->

<!-- Breaks: All sniffs MUST be located within a [CategoryName] directory. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/MissingCategoryDirSniff.php"/>
<!-- Breaks: The namespace and class name MUST follow PSR-4. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/NoNamespaceSniff.php"/>
<!-- Breaks: The namespace and class name MUST follow PSR-4. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/PartialNamespaceSniff.php"/>
<!-- Breaks: All sniffs MUST have a name, so a sniff class called just and only Sniff is not allowed. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/Category/Sniff.php"/>
<!-- Breaks: The name "Sniffs" MUST NOT be used as a category name. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/Sniffs/CategoryCalledSniffsSniff.php"/>
<!-- Breaks: No directories should exist under the [CategoryName] directory. -->
<rule ref="./Fixtures/BrokenNamingConventions/Sniffs/Category/SubDir/TooDeeplyNestedSniff.php"/>

<!-- Prevent a "no sniff were registered" error (once the above become errors). -->
<rule ref="Generic.PHP.BacktickOperator"/>
</ruleset>