diff --git a/src/Ruleset.php b/src/Ruleset.php index b6279bf9f3..81774a6b7a 100644 --- a/src/Ruleset.php +++ b/src/Ruleset.php @@ -1457,7 +1457,9 @@ public function populateTokenListeners() $sniffCode = Common::getSniffCode($sniffClass); $this->sniffCodes[$sniffCode] = $sniffClass; + $isDeprecated = false; if ($this->sniffs[$sniffClass] instanceof DeprecatedSniff) { + $isDeprecated = true; $this->deprecatedSniffs[$sniffCode] = $sniffClass; } @@ -1470,6 +1472,24 @@ public function populateTokenListeners() $tokenizers = []; $vars = get_class_vars($sniffClass); + if (empty($vars['supportedTokenizers']) === false + && $isDeprecated === false + && in_array('PHP', $vars['supportedTokenizers'], true) === false + ) { + if (in_array('CSS', $vars['supportedTokenizers'], true) === true + || in_array('JS', $vars['supportedTokenizers'], true) === true + ) { + $message = 'Scanning CSS/JS files is deprecated and support will be removed in PHP_CodeSniffer 4.0.'.PHP_EOL; + } else { + // Just in case someone has an integration with a custom tokenizer. + $message = 'Support for custom tokenizers will be removed in PHP_CodeSniffer 4.0.'.PHP_EOL; + } + + $message .= 'The %s sniff is listening for %s.'; + $message = sprintf($message, $sniffCode, implode(', ', $vars['supportedTokenizers'])); + $this->msgCache->add($message, MessageCollector::DEPRECATED); + } + if (isset($vars['supportedTokenizers']) === true) { foreach ($vars['supportedTokenizers'] as $tokenizer) { $tokenizers[$tokenizer] = $tokenizer; diff --git a/tests/Core/Filters/Filter/AcceptTest.xml b/tests/Core/Filters/Filter/AcceptTest.xml index 3d3e1de080..2800298ebf 100644 --- a/tests/Core/Filters/Filter/AcceptTest.xml +++ b/tests/Core/Filters/Filter/AcceptTest.xml @@ -8,6 +8,8 @@ */Other/Main\.php$ + + /anything/* diff --git a/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SupportedTokenizers/ImplementsDeprecatedInterfaceSniff.php b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SupportedTokenizers/ImplementsDeprecatedInterfaceSniff.php new file mode 100644 index 0000000000..af095072bd --- /dev/null +++ b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SupportedTokenizers/ImplementsDeprecatedInterfaceSniff.php @@ -0,0 +1,46 @@ + + * @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 PHP_CodeSniffer\Tests\Core\Ruleset\AbstractRulesetTestCase; + +/** + * Test the Ruleset::populateTokenListeners() method shows a deprecation notice for sniffs supporting JS and/or CSS tokenizers. + * + * @covers \PHP_CodeSniffer\Ruleset::populateTokenListeners + */ +final class PopulateTokenListenersSupportedTokenizersTest extends AbstractRulesetTestCase +{ + + /** + * The Config object. + * + * @var \PHP_CodeSniffer\Config + */ + private static $config; + + + /** + * Initialize the config and ruleset objects for this test. + * + * @beforeClass + * + * @return void + */ + public static function initializeConfig() + { + // Set up the ruleset. + $standard = __DIR__.'/PopulateTokenListenersSupportedTokenizersTest.xml'; + self::$config = new ConfigDouble(["--standard=$standard"]); + + }//end initializeConfig() + + + /** + * Verify that a deprecation notice is shown if a non-deprecated sniff supports the JS/CSS tokenizer(s). + * + * Additionally, this test verifies that: + * - No deprecation notice is thrown if the complete sniff is deprecated. + * - No deprecation notice is thrown when the sniff _also_ supports PHP. + * - No deprecation notice is thrown when no tokenizers are supported (not sure why anyone would do that, but :shrug:). + * + * {@internal The test uses a data provider to verify the messages as the _order_ of the messages depends + * on the OS on which the tests are run (order in which files are retrieved), which makes the order within the + * complete message too unpredictable to test in one go.} + * + * @param string $expected The expected message output in regex format. + * + * @dataProvider dataDeprecatedTokenizersTriggerDeprecationNotice + * + * @return void + */ + public function testDeprecatedTokenizersTriggerDeprecationNotice($expected) + { + $this->expectOutputRegex($expected); + + new Ruleset(self::$config); + + }//end testDeprecatedTokenizersTriggerDeprecationNotice() + + + /** + * Data provider. + * + * @see testDeprecatedTokenizersTriggerDeprecationNotice() + * + * @return array> + */ + public static function dataDeprecatedTokenizersTriggerDeprecationNotice() + { + $cssJsDeprecated = '`DEPRECATED: Scanning CSS/JS files is deprecated and support will be removed in PHP_CodeSniffer 4\.0\.\R'; + $cssJsDeprecated .= 'The %1$s sniff is listening for %2$s\.\R`'; + + $customTokenizer = '`DEPRECATED: Support for custom tokenizers will be removed in PHP_CodeSniffer 4\.0\.\R'; + $customTokenizer .= 'The %1$s sniff is listening for %2$s\.\R`'; + + return [ + 'Listens for CSS' => [ + 'expected' => sprintf($cssJsDeprecated, 'TestStandard.SupportedTokenizers.ListensForCSS', 'CSS'), + ], + 'Listens for JS' => [ + 'expected' => sprintf($cssJsDeprecated, 'TestStandard.SupportedTokenizers.ListensForJS', 'JS'), + ], + 'Listens for both CSS and JS' => [ + 'expected' => sprintf($cssJsDeprecated, 'TestStandard.SupportedTokenizers.ListensForCSSAndJS', 'CSS, JS'), + ], + 'Listens for CSS and something unrecognized' => [ + 'expected' => sprintf($cssJsDeprecated, 'TestStandard.SupportedTokenizers.ListensForCSSAndUnrecognized', 'CSS, Unrecognized'), + ], + 'Listens for only unrecognized tokenizers' => [ + 'expected' => sprintf($customTokenizer, 'TestStandard.SupportedTokenizers.ListensForUnrecognizedTokenizers', 'SCSS, TypeScript'), + ], + ]; + + }//end dataDeprecatedTokenizersTriggerDeprecationNotice() + + +}//end class diff --git a/tests/Core/Ruleset/PopulateTokenListenersSupportedTokenizersTest.xml b/tests/Core/Ruleset/PopulateTokenListenersSupportedTokenizersTest.xml new file mode 100644 index 0000000000..1a02eba182 --- /dev/null +++ b/tests/Core/Ruleset/PopulateTokenListenersSupportedTokenizersTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/Core/Ruleset/PopulateTokenListenersTest.php b/tests/Core/Ruleset/PopulateTokenListenersTest.php index 6f79c10da1..347ffddee7 100644 --- a/tests/Core/Ruleset/PopulateTokenListenersTest.php +++ b/tests/Core/Ruleset/PopulateTokenListenersTest.php @@ -131,31 +131,31 @@ public function testRegistersSniffsToListenToTokens($sniffClass, $expectedCount) public static function dataSniffListensToTokenss() { return [ - 'Generic.Files.EndFileNewline' => [ - 'sniffClass' => 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\Files\\EndFileNewlineSniff', + 'TestStandard.SupportedTokenizers.ListensForPHPAndCSSAndJS' => [ + 'sniffClass' => 'Fixtures\\TestStandard\\Sniffs\\SupportedTokenizers\\ListensForPHPAndCSSAndJSSniff', 'expectedCount' => 2, ], - 'Generic.NamingConventions.UpperCaseConstantName' => [ + 'Generic.NamingConventions.UpperCaseConstantName' => [ 'sniffClass' => 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\NamingConventions\\UpperCaseConstantNameSniff', 'expectedCount' => 2, ], - 'PSR1.Files.SideEffects' => [ + 'PSR1.Files.SideEffects' => [ 'sniffClass' => 'PHP_CodeSniffer\\Standards\\PSR1\\Sniffs\\Files\\SideEffectsSniff', 'expectedCount' => 1, ], - 'PSR12.ControlStructures.BooleanOperatorPlacement' => [ + 'PSR12.ControlStructures.BooleanOperatorPlacement' => [ 'sniffClass' => 'PHP_CodeSniffer\\Standards\\PSR12\\Sniffs\\ControlStructures\\BooleanOperatorPlacementSniff', 'expectedCount' => 5, ], - 'Squiz.ControlStructures.ForEachLoopDeclaration' => [ + 'Squiz.ControlStructures.ForEachLoopDeclaration' => [ 'sniffClass' => 'PHP_CodeSniffer\\Standards\\Squiz\\Sniffs\\ControlStructures\\ForEachLoopDeclarationSniff', 'expectedCount' => 1, ], - 'TestStandard.Deprecated.WithReplacement' => [ + 'TestStandard.Deprecated.WithReplacement' => [ 'sniffClass' => 'Fixtures\\TestStandard\\Sniffs\\Deprecated\\WithReplacementSniff', 'expectedCount' => 1, ], - 'TestStandard.ValidSniffs.RegisterEmptyArray' => [ + 'TestStandard.ValidSniffs.RegisterEmptyArray' => [ 'sniffClass' => 'Fixtures\\TestStandard\\Sniffs\\ValidSniffs\\RegisterEmptyArraySniff', 'expectedCount' => 0, ], @@ -313,7 +313,7 @@ public function testSetsClassAndSourceIndexes() */ public function testSetsSupportedTokenizersToPHPByDefault() { - $exclude = 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\Files\\EndFileNewlineSniff'; + $exclude = 'Fixtures\\TestStandard\\Sniffs\\SupportedTokenizers\\ListensForPHPAndCSSAndJSSniff'; $expected = ['PHP' => 'PHP']; foreach (self::$ruleset->tokenListeners as $token => $listeners) { @@ -354,7 +354,7 @@ public function testSetsSupportedTokenizersToPHPByDefault() */ public function testSetsSupportedTokenizersWhenProvidedBySniff($token) { - $sniffClass = 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\Files\\EndFileNewlineSniff'; + $sniffClass = 'Fixtures\\TestStandard\\Sniffs\\SupportedTokenizers\\ListensForPHPAndCSSAndJSSniff'; $expected = [ 'PHP' => 'PHP', 'JS' => 'JS', diff --git a/tests/Core/Ruleset/PopulateTokenListenersTest.xml b/tests/Core/Ruleset/PopulateTokenListenersTest.xml index f61ab500d0..2116048ad0 100644 --- a/tests/Core/Ruleset/PopulateTokenListenersTest.xml +++ b/tests/Core/Ruleset/PopulateTokenListenersTest.xml @@ -21,7 +21,7 @@ - + diff --git a/tests/Core/Ruleset/ProcessRulesetAutoExpandSniffsDirectoryTest.xml b/tests/Core/Ruleset/ProcessRulesetAutoExpandSniffsDirectoryTest.xml index 3b8b4c9b41..4ca8458e95 100644 --- a/tests/Core/Ruleset/ProcessRulesetAutoExpandSniffsDirectoryTest.xml +++ b/tests/Core/Ruleset/ProcessRulesetAutoExpandSniffsDirectoryTest.xml @@ -4,6 +4,7 @@ + diff --git a/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml b/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml index 8ce97e2dd3..a7c05017d0 100644 --- a/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml +++ b/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml @@ -2,6 +2,7 @@ + diff --git a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml index ab632b1959..8dee19d8e1 100644 --- a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml +++ b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml @@ -5,6 +5,7 @@ +