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

Command line parsing fail with 'Can't find the custom report class: ' when using options

jtattevinvaluein opened this issue · comments

  • PHPMD version: 2.14.0
  • PHP Version: 8.1.22
  • Installation type: composer
  • Operating System / Distribution & Version: alpine 3.16.4 on docker

Current Behavior

When running phpmd with an option (tested with --help and --exclude), the command fail with the following message :
Can't find the custom report class: cleancode

The command that was used was /root/.composer/vendor/bin/phpmd index.php json cleancode --exclude=*/vendor/*

Expected Behavior

The scan run on index.php with cleancode and output the result as json.

Downgrading to 2.13.0 work as expected

Steps To Reproduce:

  • install phpmd : composer global require --dev phpmd/phpmd:2.14
  • scan a php file without arguments to confirm that it work : /root/.composer/vendor/bin/phpmd index.php json cleancode
  • scan a php file with any arguments : /root/.composer/vendor/bin/phpmd index.php json cleancode --help or /root/.composer/vendor/bin/phpmd index.php json cleancode --exclude

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".
commented

Hello, I'll fix that. Note that you can use phpmd index.php json cleancode --exclude */vendor/* (space instead of equal before the value) meanwhile.

commented

As a side note, --exclude=*/vendor/* syntax was never supported, this part was just silently ignored in PHPMD 2.13.0 if I'm not mistaken. So it's was not actually "working".

Also can you show how you get similar issue with --help?

Hello, thank for the quick feedback, i confirm that using the space instead of equal sign make the command work as expected.

For the --help case, i'm doing this command :
/root/.composer/vendor/bin/phpmd /web/html/web/index.php json cleancode --help

On 2.14, i have Can't find the custom report class: cleancode as an output
On 2.13, i have as an output :

{
    "version": "@package_version@",
    "package": "phpmd",
    "timestamp": "2023-09-27T12:15:03+00:00",
    "files": []
}

Something that i just saw, it seem like there is no --help command, so it would seem that unknown argument was just ignored previously as you said, and now trigger this error instead of saying that the option is not allowed

To add on the previous comment :

$ /root/.composer/vendor/bin/phpmd /web/html/web/index.php json cleancode --cache
{
    "version": "@package_version@",
    "package": "phpmd",
    "timestamp": "2023-09-27T12:20:55+00:00",
    "files": []
}
$ /root/.composer/vendor/bin/phpmd /web/html/web/index.php json cleancode --help
Can't find the custom report class: cleancode
$ /root/.composer/vendor/bin/phpmd /web/html/web/index.php json cleancode --thisDoesntExist
Can't find the custom report class: cleancode

The behavior about --cache seem ok, with --help or --thisDoesntExist i would expect more an error about the argument that about the report class (but i understand that it may be a report class with argument)

commented

Issue there is that we'll now consider the 2 last arguments as output type and ruleset, and all other arguments before that to be a list of paths to scan.

And anything not being a known option is considered an argument.

Ok, so it's more an usage issue with the wrong syntax for argument than a bug, so i'm closing the ticket
Thank for the help

commented

From one side, supporting syntax --exclude=*/vendor/* would be possible and is quite a common usage and should not conflict with current usages (I doubt someone has filenames starting with --exclude= as = is generally avoided in file names) so we could implement support for it.

On the other side, making better error message for non existing option is tricky because this might be valid:

phpmd --aa --bb --cc --dd

If --aa and --bb are files/folders, --cc is a custom format and --dd a path to ruleset XML file. It's unlikely but it's technically possible.

In this case, you could still run the command like that :

phpmd ./--aa ./--bb --cc ./--dd

For example, If you want to remove a file that start with a -, you'll have to use this syntax, otherwise rm say that the arguments are not correct

Another thing that i've seen is to use the special -- argument to specify the end of the arguments (for example php does that : https://www.php.net/manual/en/features.commandline.options.php)
In this case, your command would look like :

phpmd -- --aa --bb --cc --dd
phpmd --exclude=*/vendor/* -- --aa --bb --cc --dd

Note: It's only from my experience of command line to try to help, i don't know if/how it could break current usage and if it's adapted to this project.

commented

Yep, that's a great idea.

I added the -- syntax and so the validation to disallow arguments starting with - unless -- separator is used which will also be explicitly suggested by the error message:

Unknown option --help.
If you intend to use "--help" as a value for ruleset argument, use the explicit argument separator:
phpmd --exclude=*/vendor/* -- foo/test.php text foo/phpmd.xml --help