From 6a381ae05f544c68d02ab57c906a26868dbb1f50 Mon Sep 17 00:00:00 2001 From: func0der <529819+func0der@users.noreply.github.com> Date: Mon, 12 May 2025 13:56:38 +0200 Subject: [PATCH 1/2] GH-1083 Add possibility to have ignored unused function parameters --- .../UnusedFunctionParameterSniff.php | 22 ++- .../UnusedFunctionParameterUnitTest.4.inc | 147 ++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.4.inc diff --git a/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php b/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php index e076b83dce..db1044e288 100644 --- a/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php +++ b/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php @@ -56,6 +56,11 @@ class UnusedFunctionParameterSniff implements Sniff '__debuginfo' => true, ]; + /** + * A list of prefixes for parameter names that indicate, they should be ignored. + */ + private $ignorePrefixes = ['$_']; + /** * Returns an array of tokens this test wants to listen for. @@ -127,7 +132,22 @@ public function process(File $phpcsFile, $stackPtr) return; } - foreach ($methodParams as $param) { + $filteredMethodParams = array_filter( + $methodParams, + function ($parameter) { + $ignoreVariable = array_reduce( + $this->ignorePrefixes, + function ($previous, $ignorePrefix) use ($parameter) { + return $previous || strpos($parameter['name'], $ignorePrefix) === 0; + }, + false + ); + + return $ignoreVariable === false; + } + ); + + foreach ($filteredMethodParams as $param) { if (isset($param['property_visibility']) === true) { // Ignore constructor property promotion. continue; diff --git a/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.4.inc b/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.4.inc new file mode 100644 index 0000000000..71bb7d1546 --- /dev/null +++ b/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.4.inc @@ -0,0 +1,147 @@ + $b; + +// phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[] Exception + +function oneParam(Exception $_) { + return 'foobar'; +} + +function moreParamFirst(Exception $_, LogicException $bar) { + return 'foobar' . $bar; +} + +function moreParamSecond(LogicException $bar, Exception $_) { + return 'foobar' . $bar; +} +// phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[] + +class ConstructorPropertyPromotionNoContentInMethod { + public function __construct(protected int $_) {} +} + +class ConstructorPropertyPromotionWithContentInMethod { + public function __construct(protected int $_, $toggle = true) { + if ($toggle === true) { + doSomething(); + } + } +} + +$found = in_array_cb($needle, $haystack, fn($_, $needle) => $needle === 5); + + +/* + * Don't adjust the error code for closures and arrow functions in extended classes/classes implementing interfaces. + */ +class MyExtendedClass extends SomeClass { + public function something($a, $b) { + $c = $a + $b; + $closure = function ($c, $_) { + return $c * 2; + }; + } +} + + +/** + * Magic methods must match the function signature dictated by PHP. + * Flagging unused parameters leads to notices which cannot be solved. + */ + +class MagicMethodsWithParamsNotDictatedByPHP { + public $foo; + public function __construct($foo, $_) { + $this->foo = $foo; + } + + public function __invoke($foo, $_) { + $this->foo = $foo; + } +} + +/** + * Unused parameters in magic methods which have flexible function signatures + * where the method potentially overloads a parent method should still be flagged, + * but should use the `FoundInExtendedClassAfterLastUsed` error code. + */ +class MagicMethodsWithParamsNotDictatedByPHPInChildClass extends SomeParent{ + public $foo; + public function __construct($foo, $_) { + $this->foo = $foo; + } + + public function __invoke($foo, $_) { + $this->foo = $foo; + } +} + +/** + * Should trigger the sniff as this method is not part of an interface. + */ +class MethodThrowsException { + public function throwsException($_) { + throw new Exception(); + } +} From 651e1cdd57a7ba268f77caee90285506a90e2655 Mon Sep 17 00:00:00 2001 From: func0der <529819+func0der@users.noreply.github.com> Date: Mon, 12 May 2025 14:06:33 +0200 Subject: [PATCH 2/2] GH-1083 Add missing variable definition --- .../Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php b/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php index db1044e288..d22fbe78e9 100644 --- a/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php +++ b/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php @@ -58,6 +58,8 @@ class UnusedFunctionParameterSniff implements Sniff /** * A list of prefixes for parameter names that indicate, they should be ignored. + * + * @var string[] */ private $ignorePrefixes = ['$_'];