phpmd / phpmd

PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD. PHPMD can be seen as an user friendly frontend application for the raw metrics stream measured by PHP Depend.

Home Page:https://phpmd.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

False positive on "Avoid unused private methods"

llaville opened this issue · comments

  • PHPMD version: 2.15.0snapshot202312110823
  • PHP Version: 8.2.15
  • Installation type: (phar file/ composer) PHAR (with deprecated errors : read my comment)
  • Operating System / Distribution & Version: Linux Ubuntu 22..04.3 LTS

Current Behavior

Report a violation about a private method that is called as callback on an array_filter function.

Expected Behavior

Do not report violation on such context

Steps To Reproduce:

When running command php phpmd.phar src ansi unusedcode on source code of https://github.com/composer-unused/symbol-parser/tree/0.2.2, I got false positive

FILE: /shared/backups/forks/symbol-parser/src/Symbol/Loader/FileSymbolLoader.php
--------------------------------------------------------------------------------
 139 | VIOLATION | Avoid unused private methods such as 'filterExistingDir'.


FILE: /shared/backups/forks/symbol-parser/src/Symbol/Loader/PsrSymbolLoader.php
-------------------------------------------------------------------------------
 22  | VIOLATION | Avoid unused local variables such as '$dir'.

Found 2 violations and 0 errors in 568ms

NOTE I've removed deprecated error displayed to have a better readability of report !

On report, 139 | VIOLATION | Avoid unused private methods such as 'filterExistingDir'. is false because private method is used by this call => https://github.com/composer-unused/symbol-parser/blob/0.2.2/src/Symbol/Loader/FileSymbolLoader.php#L53

Checks before submitting

  • Be sure that there isn't already an issue about this. See: Issues list
  • Be sure that there isn't already a pull request about this. See: Pull requests
  • I have added every step to reproduce the bug.
  • If possible I added relevant code examples.
  • This issue is about 1 bug and nothing more.
  • The issue has a descriptive title. For example: "JSON rendering failed on Windows for filenames with space".

I know it's doesn't solve the issue in phpmd, but could you try using an arrow function as a workaround and see if that works for your code base?

$sourceFolders = array_filter($sourceFolders, fn (string $dir): bool => $this->filterExistingDir($dir));

In 8.1 you could use a first-class closure:

$sourceFolders = array_filter($sourceFolders, $this->filterExistingDir(...));

@AJenbo I agree with you : there are always alternative to write code in another way.
But if I wrote this report that is just to share and keep PHPMD team aware of false violation reporting !

$sourceFolders = array_filter($sourceFolders, fn (string $dir): bool => $this->filterExistingDir($dir));

Feature available since PHP 7.4 ( https://www.php.net/manual/en/functions.arrow.php )

And repo https://github.com/composer-unused/symbol-parser code base require at least PHP 7.4 to run ;-)

Yeah I made sure to check your repo before suggesting it ;)

It's not my repo. I'm just a contributor !

Sorry

commented

While $this->filterExistingDir() is straightforward to recognize as a call of the private method filterExistingDir (with current PDepend parser abilities), recognizing that [$this, 'filterExistingDir'] is also a call to private method is more tricky. It depends on where it got passed (if passed to a callable parameter or put in a value that is later triggered with () or with call_user_func() or itself passed to a callable parameter, etc.) so we would have to track it potentially very far to actually know that it indeed represent a callable.

We could not check where it goes and in the doubt assume that an array of 1 element being $this and another element being a string (such as [$this, 'filterExistingDir']) is very likely to be used as a callable and so check the string statically and not raise the violation.

We would still have issue as this array can be constructed dynamically, and also the string can be obtained by concatenation or from a non-static value.

So with some effort we would obtain a smarter result but still with false positives and false negatives.

commented

NOTE I've removed deprecated error displayed to have a better readability of report !

Deprecations are expected to happen when running the PHAR version of PHPMD (because it supports all versions of PHP from 5.3)

You can use:

php -d error_reporting=8191 phpmd.phar source text rules.xml

Using composer install you won't have any deprecation raised.

commented

Progress of this issue will be tracked on #897

For what it's worth PHPStan's latest updates sees [0 => object, 1 => 'method_name'] as a callable, even if it doesn't see it used. I think this is a fair assumption as it is indeed callable. It would require that we can see what object it is, and can use the string to look for existing methods on that class. Stan is also able to track the construction of arrays that we are not able to.

commented

Cool so #1068 is the way to go. 👍

First thing first recognize $this as an easy win which likely represent majority of the use cases.

Then we can try to identify clone $this, new self and the like as best-effort (we can detect in the body of the current method, but if it's passed argument or dynamically transformed value, we'll be beaten, though it might not be a big concern as those should not happen in clean code)