Skip to content

Commit fcdcf4a

Browse files
claytonrcarterkukulich
authored andcommitted
SlevomatCodingStandard.Functions.UnusedParameter: New option "allowedParameterPatterns" to suppress check for specific parameter names
1 parent 72b4009 commit fcdcf4a

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22

33
namespace SlevomatCodingStandard\Sniffs\Functions;
44

5+
use Exception;
56
use PHP_CodeSniffer\Files\File;
67
use PHP_CodeSniffer\Sniffs\Sniff;
78
use PHP_CodeSniffer\Util\Tokens;
89
use SlevomatCodingStandard\Helpers\FunctionHelper;
10+
use SlevomatCodingStandard\Helpers\SniffSettingsHelper;
911
use SlevomatCodingStandard\Helpers\SuppressHelper;
1012
use SlevomatCodingStandard\Helpers\TokenHelper;
1113
use SlevomatCodingStandard\Helpers\VariableHelper;
1214
use function array_merge;
1315
use function in_array;
16+
use function preg_match;
1417
use function sprintf;
18+
use function substr;
1519
use const T_COMMA;
1620
use const T_VARIABLE;
1721

@@ -23,6 +27,9 @@ class UnusedParameterSniff implements Sniff
2327

2428
private const NAME = 'SlevomatCodingStandard.Functions.UnusedParameter';
2529

30+
/** @var list<string> */
31+
public array $allowedParameterPatterns = [];
32+
2633
/**
2734
* @return array<int, (int|string)>
2835
*/
@@ -70,7 +77,10 @@ public function process(File $phpcsFile, $functionPointer): void
7077
continue;
7178
}
7279

73-
if (VariableHelper::isUsedInScope($phpcsFile, $functionPointer, $parameterPointer)) {
80+
if (
81+
$this->variableIsSuppressedViaName($tokens[$parameterPointer]['content']) ||
82+
VariableHelper::isUsedInScope($phpcsFile, $functionPointer, $parameterPointer)
83+
) {
7484
$currentPointer = $parameterPointer + 1;
7585
continue;
7686
}
@@ -104,4 +114,19 @@ private function getSniffName(string $sniffName): string
104114
return sprintf('%s.%s', self::NAME, $sniffName);
105115
}
106116

117+
private function variableIsSuppressedViaName(string $variableName): bool
118+
{
119+
foreach (SniffSettingsHelper::normalizeArray($this->allowedParameterPatterns) as $allowedParamPattern) {
120+
if (!SniffSettingsHelper::isValidRegularExpression($allowedParamPattern)) {
121+
throw new Exception(sprintf('%s is not valid PCRE pattern.', $allowedParamPattern));
122+
}
123+
124+
if (preg_match($allowedParamPattern, substr($variableName, 1)) === 1) {
125+
return true;
126+
}
127+
}
128+
129+
return false;
130+
}
131+
107132
}

doc/functions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ Looks for unused inherited variables passed to closure via `use`.
131131

132132
Looks for unused parameters.
133133

134+
This sniff provides the following setting:
135+
136+
* `allowedParameterPatterns`: allows to configure which parameters are always allowed, even if unused. This is an array of regular expressions (PCRE) with delimiters, but without the leading `$` from variable names. (For example, use `[/^_/]` to allow parameters that start with an underscore, like `$_unused`.)
137+
134138
#### SlevomatCodingStandard.Functions.UselessParameterDefaultValue 🚧
135139

136140
Looks for useless parameter default value.

tests/Sniffs/Functions/UnusedParameterSniffTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace SlevomatCodingStandard\Sniffs\Functions;
44

55
use SlevomatCodingStandard\Sniffs\TestCase;
6+
use Throwable;
67

78
class UnusedParameterSniffTest extends TestCase
89
{
@@ -40,4 +41,43 @@ public function testErrors(): void
4041
);
4142
}
4243

44+
public function testAllowedParameterSetting(): void
45+
{
46+
$report = self::checkFile(__DIR__ . '/data/unusedParameterErrors.php', [
47+
'allowedParameterPatterns' => ['~^a$~'],
48+
], [UnusedParameterSniff::CODE_UNUSED_PARAMETER]);
49+
50+
self::assertSame(2, $report->getErrorCount());
51+
52+
self::assertSniffError($report, 3, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $b.');
53+
self::assertSniffError($report, 66, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $b.');
54+
55+
$report = self::checkFile(__DIR__ . '/data/unusedParameterErrors.php', [
56+
'allowedParameterPatterns' => ['~^b$~'],
57+
], [UnusedParameterSniff::CODE_UNUSED_PARAMETER]);
58+
59+
self::assertSame(10, $report->getErrorCount());
60+
61+
self::assertSniffError($report, 3, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
62+
self::assertSniffError($report, 7, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
63+
self::assertSniffError($report, 14, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
64+
self::assertSniffError($report, 19, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
65+
self::assertSniffError($report, 26, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
66+
self::assertSniffError($report, 35, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
67+
self::assertSniffError($report, 40, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
68+
self::assertSniffError($report, 47, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
69+
self::assertSniffError($report, 51, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
70+
self::assertSniffError($report, 53, UnusedParameterSniff::CODE_UNUSED_PARAMETER, 'Unused parameter $a.');
71+
}
72+
73+
public function testThrowExceptionForInvalidPattern(): void
74+
{
75+
$this->expectException(Throwable::class);
76+
77+
self::checkFile(
78+
__DIR__ . '/data/unusedParameterErrors.php',
79+
['allowedParameterPatterns' => ['invalidPattern']],
80+
);
81+
}
82+
4383
}

0 commit comments

Comments
 (0)