Skip to content

Commit aa923c4

Browse files
authored
Merge 651e1cd into 6f9d29e
2 parents 6f9d29e + 651e1cd commit aa923c4

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ class UnusedFunctionParameterSniff implements Sniff
5656
'__debuginfo' => true,
5757
];
5858

59+
/**
60+
* A list of prefixes for parameter names that indicate, they should be ignored.
61+
*
62+
* @var string[]
63+
*/
64+
private $ignorePrefixes = ['$_'];
65+
5966

6067
/**
6168
* Returns an array of tokens this test wants to listen for.
@@ -127,7 +134,22 @@ public function process(File $phpcsFile, $stackPtr)
127134
return;
128135
}
129136

130-
foreach ($methodParams as $param) {
137+
$filteredMethodParams = array_filter(
138+
$methodParams,
139+
function ($parameter) {
140+
$ignoreVariable = array_reduce(
141+
$this->ignorePrefixes,
142+
function ($previous, $ignorePrefix) use ($parameter) {
143+
return $previous || strpos($parameter['name'], $ignorePrefix) === 0;
144+
},
145+
false
146+
);
147+
148+
return $ignoreVariable === false;
149+
}
150+
);
151+
152+
foreach ($filteredMethodParams as $param) {
131153
if (isset($param['property_visibility']) === true) {
132154
// Ignore constructor property promotion.
133155
continue;
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
function foo($a, $_) {
4+
return $a * 2;
5+
}
6+
7+
function baz($a, $_) {
8+
echo "baz({$a});";
9+
}
10+
11+
class Foo implements Bar {
12+
function fooBar($_, $_) {
13+
return;
14+
}
15+
}
16+
17+
print foo( 'PARAMETER' );
18+
print "\n";
19+
20+
$foo = function ($a, $_) {
21+
return $a * 2;
22+
};
23+
24+
25+
/*
26+
* The function signature of methods in extended classes and implemented
27+
* interfaces has to mirror the parent class/interface.
28+
* The overloaded method may not use all params.
29+
*/
30+
31+
class MyClass {
32+
public function something($a, $_) {
33+
return $a * 2;
34+
}
35+
}
36+
37+
class MyExtendedClass extends SomeClass {
38+
public function something($a, $_) {
39+
return $a * 2;
40+
}
41+
}
42+
43+
class MyExtendedClass implements SomeInterface {
44+
public function something($a, $_) {
45+
return $a * 2;
46+
}
47+
}
48+
49+
50+
/*
51+
* Functions may not use all params passed to them.
52+
* Report different violations for params *before* and *after* the last param used.
53+
*/
54+
55+
function something($_) {
56+
return 'foobar';
57+
}
58+
59+
function myCallback($a, $_, $c, $_) {
60+
return $a * $c;
61+
}
62+
63+
fn ($_, $b) => $b;
64+
65+
// phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[] Exception
66+
67+
function oneParam(Exception $_) {
68+
return 'foobar';
69+
}
70+
71+
function moreParamFirst(Exception $_, LogicException $bar) {
72+
return 'foobar' . $bar;
73+
}
74+
75+
function moreParamSecond(LogicException $bar, Exception $_) {
76+
return 'foobar' . $bar;
77+
}
78+
// phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[]
79+
80+
class ConstructorPropertyPromotionNoContentInMethod {
81+
public function __construct(protected int $_) {}
82+
}
83+
84+
class ConstructorPropertyPromotionWithContentInMethod {
85+
public function __construct(protected int $_, $toggle = true) {
86+
if ($toggle === true) {
87+
doSomething();
88+
}
89+
}
90+
}
91+
92+
$found = in_array_cb($needle, $haystack, fn($_, $needle) => $needle === 5);
93+
94+
95+
/*
96+
* Don't adjust the error code for closures and arrow functions in extended classes/classes implementing interfaces.
97+
*/
98+
class MyExtendedClass extends SomeClass {
99+
public function something($a, $b) {
100+
$c = $a + $b;
101+
$closure = function ($c, $_) {
102+
return $c * 2;
103+
};
104+
}
105+
}
106+
107+
108+
/**
109+
* Magic methods must match the function signature dictated by PHP.
110+
* Flagging unused parameters leads to notices which cannot be solved.
111+
*/
112+
113+
class MagicMethodsWithParamsNotDictatedByPHP {
114+
public $foo;
115+
public function __construct($foo, $_) {
116+
$this->foo = $foo;
117+
}
118+
119+
public function __invoke($foo, $_) {
120+
$this->foo = $foo;
121+
}
122+
}
123+
124+
/**
125+
* Unused parameters in magic methods which have flexible function signatures
126+
* where the method potentially overloads a parent method should still be flagged,
127+
* but should use the `FoundInExtendedClassAfterLastUsed` error code.
128+
*/
129+
class MagicMethodsWithParamsNotDictatedByPHPInChildClass extends SomeParent{
130+
public $foo;
131+
public function __construct($foo, $_) {
132+
$this->foo = $foo;
133+
}
134+
135+
public function __invoke($foo, $_) {
136+
$this->foo = $foo;
137+
}
138+
}
139+
140+
/**
141+
* Should trigger the sniff as this method is not part of an interface.
142+
*/
143+
class MethodThrowsException {
144+
public function throwsException($_) {
145+
throw new Exception();
146+
}
147+
}

0 commit comments

Comments
 (0)