Skip to content
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

Config: display user-friendly message when invalid generator is passed #771

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

rodrigoprimo
Copy link
Contributor

Description

This PR improves how Config::processLongArgument() handles the --generator parameter to display a user-friendly message if an invalid generator name is passed. Before, an invalid generator name caused a fatal error.

I have checked, and it is not possible to add custom generators using third-party code (at least not without adding files to the PHPCS directory). This is because the Runner class only loads generators found in the src/Generator/ directory:

$class = 'PHP_CodeSniffer\Generators\\'.$this->config->generator;
$generator = new $class($ruleset);

So, it should be fine to limit the list of valid generators added in this PR to only the three generators provided by PHPCS.

Suggested changelog entry

Config: display a user-friendly message if an invalid generator name is passed in the command line

Related issues/external references

Fixes #709

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
    • This change is only breaking for integrators, not for external standards or end-users.
  • Documentation improvement

PR checklist

  • I have checked there is no other PR open for the same change.
  • I have read the Contribution Guidelines.
  • I grant the project the right to include and distribute the code under the BSD-3-Clause license (and I have the right to grant these rights).
  • I have added tests to cover my changes.
  • I have verified that the code complies with the projects coding standards.
  • [Required for new sniffs] I have added XML documentation for the sniff.

This commit improves how `Config::processLongArgument()` handles the
`--generator` parameter. Now it will show a user-friendly message if an
invalid generator name is passed. Before, an invalid generator name
caused a fatal error.
@rodrigoprimo
Copy link
Contributor Author

@jrfnl, while working on this PR, I noticed that, besides what I reported in #709, it is possible to trigger a different PHP fatal error if Generator is passed as the name of the generator:

$ phpcs test.php --generator=Generator --standard=Generic
PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class PHP_CodeSniffer\Generators\Generator in src/Runner.php:98
Stack trace:
#0 bin/phpcs(14): PHP_CodeSniffer\Runner->runPHPCS()
#1 {main}
  thrown in src/Runner.php on line 98

This happens because PHPCS tries to instantiate anything that it finds in the src/Generator directory:

$class = 'PHP_CodeSniffer\Generators\\'.$this->config->generator;
$generator = new $class($ruleset);

The change suggested in this PR prevents this fatal error from happening, at least when using PHPCS in the command line. But I'm mentioning it anyway in case we want to do something else about it.

@rodrigoprimo
Copy link
Contributor Author

Looking into the unrelated test that failed in the CI build.

@jrfnl
Copy link
Member

jrfnl commented Dec 13, 2024

Looking into the unrelated test that failed in the CI build.

Eh.. the test failure is not unrelated...

@rodrigoprimo rodrigoprimo force-pushed the generator-param-error-handling branch from 7141e6d to 6bb661d Compare December 18, 2024 14:58
@rodrigoprimo
Copy link
Contributor Author

@jrfnl, I dropped the commit that changed testDeprecatedSniffsListDoesNotShowNeedsCsMode() and added a new commit to ensure that the code handles the --generator argument in a case-insensitive way. This PR is ready for another review.

Copy link
Member

@jrfnl jrfnl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigoprimo Thanks for updating this. I have left some comments inline, mostly nitpicks/dotting of the i's and crossing the t's.

Other than that, this is looking good to go into the 3.12.0 release.

src/Config.php Outdated
*
* @var array<string, string>
*/
private static $validGenerators = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for making this property static ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this property static because I see its value as common for all instances of this class and not something that will change depending on the instance of the class. Do you see other reasons not to make it static?

Anyway, I had to change it to an object property to be able to manipulate its value when generating the error message (copying the value of the property before manipulating it seemed too much). See #771 (comment)

src/Config.php Outdated Show resolved Hide resolved
src/Config.php Outdated Show resolved Hide resolved
src/Config.php Outdated
$lowerCaseGeneratorName = strtolower($generatorName);

if (isset(self::$validGenerators[$lowerCaseGeneratorName]) === false) {
$validOptions = implode(', ', array_values(self::$validGenerators));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the array_values() really needed here ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also wondering if for readability, the last comma should be replaced with " and " ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the array_values() really needed here ?

Ops, no. It was added by mistake.

Also wondering if for readability, the last comma should be replaced with " and " ?

Yes, I think it is slightly better, and I used it in the original version. But then, when I moved to store the list of valid generators in a class property and used implode() to get the string with the name of the generators, I removed "and", assuming that the text is good enough without it, still correct and the code is slightly simpler.

As you are asking, I'm assuming you prefer the version with the "and," so I went ahead and added it. I'm not super happy with my approach using array_pop(), but I couldn't think of anything better. Please let me know if you have another suggestion.

Using array_pop() meant that I had to change Config::$validGenerators to an object property instead of a class property which is related to another comment you left.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, but this is supposed to be an unchangeable array (to become a class constant later on as discussed in previous comments) and the use of array_pop() explicitly changes the array (by reference) and would block the future change to make this a class constant. See: https://3v4l.org/QrM61

While the change of the property value would not currently be problematic (as a second --generator=... argument is ignored anyway), it does make the code less stable, so I'd like to see an alternative solution for this.

src/Config.php Outdated Show resolved Hide resolved
tests/Core/Config/GeneratorArgTest.php Outdated Show resolved Hide resolved
tests/Core/Config/GeneratorArgTest.php Show resolved Hide resolved
@jrfnl jrfnl added this to the 3.12.0 milestone Dec 19, 2024
@rodrigoprimo rodrigoprimo force-pushed the generator-param-error-handling branch from a6ddc1e to 541e2ef Compare December 20, 2024 00:11
@rodrigoprimo
Copy link
Contributor Author

Thanks for your additional comments, @jrfnl. I pushed a new commit addressing all of them. Please take another look when you get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PHP fatal error when user passes an invalid generator
2 participants