Skip to content

4.0 | File::addMessage(): do not ignore Internal errors when scanning selectively #98

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
merged 2 commits into from
Apr 15, 2025
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
6 changes: 4 additions & 2 deletions src/Files/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -865,9 +865,11 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s
}

// Filter out any messages for sniffs that shouldn't have run
// due to the use of the --sniffs command line argument.
// due to the use of the --sniffs or --exclude command line argument,
// but don't filter out "Internal" messages.
if ($includeAll === false
&& ((empty($this->configCache['sniffs']) === false
&& (($parts[0] !== 'Internal'
&& empty($this->configCache['sniffs']) === false
&& in_array(strtolower($listenerCode), $this->configCache['sniffs'], true) === false)
|| (empty($this->configCache['exclude']) === false
&& in_array(strtolower($listenerCode), $this->configCache['exclude'], true) === true))
Expand Down
18 changes: 16 additions & 2 deletions src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,25 @@ public function getErrorList($testFile='')
* The key of the array should represent the line number and the value
* should represent the number of warnings that should occur on that line.
*
* @param string $testFile The name of the file being tested.
*
* @return array<int, int>
*/
public function getWarningList()
public function getWarningList($testFile='')
{
return [];
switch ($testFile) {
case 'ByteOrderMarkUnitTest.3.inc':
case 'ByteOrderMarkUnitTest.4.inc':
case 'ByteOrderMarkUnitTest.5.inc':
if ((bool) ini_get('short_open_tag') === false) {
// Warning about "no code found in file".
return [1 => 1];
}
return [];

default:
return [];
}

}//end getWarningList()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@ public function getErrorList($testFile='')
public function getWarningList($testFile='')
{
if ($testFile === 'DisallowAlternativePHPTagsUnitTest.2.inc') {
// Check if the Internal.NoCodeFound error can be expected on line 1.
$option = (bool) ini_get('short_open_tag');
$line1 = 1;
if ($option === true) {
$line1 = 0;
}

return [
1 => $line1,
2 => 1,
3 => 1,
4 => 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,15 @@ public function getErrorList($testFile='')
public function getWarningList($testFile='')
{
switch ($testFile) {
case 'DisallowShortOpenTagUnitTest.1.inc':
return [];
case 'DisallowShortOpenTagUnitTest.3.inc':
// Check if the Internal.NoCodeFound error can be expected on line 1.
$option = (bool) ini_get('short_open_tag');
$line1 = 1;
if ($option === true) {
$line1 = 0;
}
return [
1 => $line1,
3 => 1,
6 => 1,
11 => 1,
Expand Down
11 changes: 10 additions & 1 deletion src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,19 @@ public function getErrorList($testFile='')
* The key of the array should represent the line number and the value
* should represent the number of warnings that should occur on that line.
*
* @param string $testFile The name of the file being tested.
*
* @return array<int, int>
*/
public function getWarningList()
public function getWarningList($testFile='')
{
if ($testFile === 'EmbeddedPhpUnitTest.24.inc'
&& (bool) ini_get('short_open_tag') === false
) {
// Warning about "no code found in file".
return [1 => 1];
}

return [];

}//end getWarningList()
Expand Down
22 changes: 11 additions & 11 deletions tests/Core/ErrorSuppressionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,15 +510,15 @@ public static function dataNestedSuppressLine()

// Process with line suppression nested within disable/enable suppression.
'disable/enable: slash comment, next line nested single line suppression' => [
'before' => '// phpcs:disable'.PHP_EOL.'// phpcs:ignore',
'before' => "// phpcs:disable\n// phpcs:ignore",
'after' => '// phpcs:enable',
],
'disable/enable: slash comment, with @, next line nested single line suppression' => [
'before' => '// @phpcs:disable'.PHP_EOL.'// @phpcs:ignore',
'before' => "// @phpcs:disable\n// @phpcs:ignore",
'after' => '// @phpcs:enable',
],
'disable/enable: hash comment, next line nested single line suppression' => [
'before' => '# @phpcs:disable'.PHP_EOL.'# @phpcs:ignore',
'before' => "# @phpcs:disable\n# @phpcs:ignore",
'after' => '# @phpcs:enable',
],
];
Expand Down Expand Up @@ -689,7 +689,7 @@ public static function dataSuppressFile()
'before' => '/* phpcs:ignoreFile */',
],
'ignoreFile: start of file, multi-line star comment' => [
'before' => '/*'.PHP_EOL.' phpcs:ignoreFile'.PHP_EOL.' */',
'before' => "/*\n phpcs:ignoreFile\n */",
],
'ignoreFile: start of file, single-line docblock comment' => [
'before' => '/** phpcs:ignoreFile */',
Expand Down Expand Up @@ -771,11 +771,11 @@ public static function dataDisableSelected()
'expectedErrors' => 1,
],
'disable: single sniff, docblock' => [
'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ',
'before' => "/**\n * phpcs:disable Generic.Commenting.Todo\n */ ",
'expectedErrors' => 1,
],
'disable: single sniff, docblock, with @' => [
'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ',
'before' => "/**\n * @phpcs:disable Generic.Commenting.Todo\n */ ",
'expectedErrors' => 1,
],

Expand All @@ -784,7 +784,7 @@ public static function dataDisableSelected()
'before' => '// phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant',
],
'disable: multiple sniff in multiple comments' => [
'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:disable Generic.PHP.LowerCaseConstant',
'before' => "// phpcs:disable Generic.Commenting.Todo\n// phpcs:disable Generic.PHP.LowerCaseConstant",
],

// Selectiveness variations.
Expand All @@ -805,17 +805,17 @@ public static function dataDisableSelected()

// Wrong category/sniff/code.
'disable: wrong error code and category' => [
'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments'.PHP_EOL.' */ ',
'before' => "/**\n * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments\n */ ",
'expectedErrors' => 1,
'expectedWarnings' => 1,
],
'disable: wrong category, docblock' => [
'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Files'.PHP_EOL.' */ ',
'before' => "/**\n * phpcs:disable Generic.Files\n */ ",
'expectedErrors' => 1,
'expectedWarnings' => 1,
],
'disable: wrong category, docblock, with @' => [
'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Files'.PHP_EOL.' */ ',
'before' => "/**\n * @phpcs:disable Generic.Files\n */ ",
'expectedErrors' => 1,
'expectedWarnings' => 1,
],
Expand Down Expand Up @@ -1070,7 +1070,7 @@ public static function dataIgnoreSelected()
'expectedWarnings' => 1,
],
'disable: single sniff; ignore: single sniff' => [
'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:ignore Generic.PHP.LowerCaseConstant',
'before' => "// phpcs:disable Generic.Commenting.Todo\n// phpcs:ignore Generic.PHP.LowerCaseConstant",
'expectedErrors' => 1,
'expectedWarnings' => 0,
],
Expand Down
126 changes: 126 additions & 0 deletions tests/Core/File/AddMessageSelectiveInternalHandlingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php
/**
* Tests that handling of Internal errors in combination with sniff selection.
*
* @copyright 2025 PHPCSStandards and contributors
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
*/

namespace PHP_CodeSniffer\Tests\Core\File;

use PHP_CodeSniffer\Files\DummyFile;
use PHP_CodeSniffer\Ruleset;
use PHP_CodeSniffer\Tests\ConfigDouble;
use PHPUnit\Framework\TestCase;

/**
* Tests that handling of Internal errors in combination with sniff selection.
*
* @covers \PHP_CodeSniffer\Files\File::addMessage
*/
final class AddMessageSelectiveInternalHandlingTest extends TestCase
{


/**
* Verify that if an Internal code is silenced from the ruleset, it will stay silenced, independently of sniff selection.
*
* @param string $sniffs Sniff selection.
* @param string $exclude Sniff exclusions.
*
* @dataProvider dataSniffSelection
*
* @return void
*/
public function testRulesetIgnoredInternalErrorIsIgnored($sniffs, $exclude)
{
$phpcsFile = $this->getPhpcsFile($sniffs, $exclude);

$added = $phpcsFile->addError('No code found', 0, 'Internal.NoCodeFound');
$this->assertFalse($added);

}//end testRulesetIgnoredInternalErrorIsIgnored()


/**
* Verify that if an Internal code is NOT silenced from the ruleset, sniff selection doesn't silence it.
*
* @param string $sniffs Sniff selection.
* @param string $exclude Sniff exclusions.
*
* @dataProvider dataSniffSelection
*
* @return void
*/
public function testOtherInternalErrorIsNotIgnored($sniffs, $exclude)
{
$phpcsFile = $this->getPhpcsFile($sniffs, $exclude);

$added = $phpcsFile->addError('Some other error', 0, 'Internal.SomeError');
$this->assertTrue($added);

}//end testOtherInternalErrorIsNotIgnored()


/**
* Data provider.
*
* @see testA()
*
* @return array<string, array<string, string>>
*/
public static function dataSniffSelection()
{
return [
'Ruleset only, no CLI selection' => [
'sniffs' => '',
'exclude' => '',
],
'Ruleset + CLI sniffs selection' => [
'sniffs' => 'Generic.Files.ByteOrderMark,Generic.PHP.DisallowShortOpenTag',
'exclude' => '',
],
'Ruleset + CLI exclude selection' => [
'sniffs' => '',
'exclude' => 'Generic.Files.ByteOrderMark,Generic.PHP.DisallowShortOpenTag',
],
];

}//end dataSniffSelection()


/**
* Test Helper to get a File object for use in these tests.
*
* @param string $sniffs Sniff selection.
* @param string $exclude Sniff exclusions.
*
* @return \PHP_CodeSniffer\Files\DummyFile
*/
private function getPhpcsFile($sniffs, $exclude)
{
// Set up the ruleset.
$standard = __DIR__.'/AddMessageSelectiveInternalHandlingTest.xml';
$args = ["--standard=$standard"];

if (empty($sniffs) === false) {
$args[] = "--sniffs=$sniffs";
}

if (empty($exclude) === false) {
$args[] = "--exclude=$exclude";
}

$config = new ConfigDouble($args);
$ruleset = new Ruleset($config);

$content = '<?php '."\necho 'hello!';\n";
$phpcsFile = new DummyFile($content, $ruleset, $config);
$phpcsFile->parse();

return $phpcsFile;

}//end getPhpcsFile()


}//end class
9 changes: 9 additions & 0 deletions tests/Core/File/AddMessageSelectiveInternalHandlingTest.xml
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="AddMessageSelectiveInternalHandlingTest" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/PHPCSStandards/PHP_CodeSniffer/master/phpcs.xsd">

<rule ref="Internal.NoCodeFound">
<severity>0</severity>
</rule>

<rule ref="PSR1"/>
</ruleset>