Skip to content

GH-1083 Add possibility to have ignored unused function parameters #1093

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ class UnusedFunctionParameterSniff implements Sniff
'__debuginfo' => true,
];

/**
* A list of prefixes for parameter names that indicate, they should be ignored.
*
* @var string[]
*/
private $ignorePrefixes = ['$_'];


/**
* Returns an array of tokens this test wants to listen for.
Expand Down Expand Up @@ -127,7 +134,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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php

function foo($a, $_) {
return $a * 2;
}

function baz($a, $_) {
echo "baz({$a});";
}

class Foo implements Bar {
function fooBar($_, $_) {
return;
}
}

print foo( 'PARAMETER' );
print "\n";

$foo = function ($a, $_) {
return $a * 2;
};


/*
* The function signature of methods in extended classes and implemented
* interfaces has to mirror the parent class/interface.
* The overloaded method may not use all params.
*/

class MyClass {
public function something($a, $_) {
return $a * 2;
}
}

class MyExtendedClass extends SomeClass {
public function something($a, $_) {
return $a * 2;
}
}

class MyExtendedClass implements SomeInterface {
public function something($a, $_) {
return $a * 2;
}
}


/*
* Functions may not use all params passed to them.
* Report different violations for params *before* and *after* the last param used.
*/

function something($_) {
return 'foobar';
}

function myCallback($a, $_, $c, $_) {
return $a * $c;
}

fn ($_, $b) => $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();
}
}