-
-
Notifications
You must be signed in to change notification settings - Fork 61
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
base: master
Are you sure you want to change the base?
Config: display user-friendly message when invalid generator is passed #771
Conversation
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.
@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 $ 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 PHP_CodeSniffer/src/Runner.php Lines 97 to 98 in 3d14d00
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. |
Looking into the unrelated test that failed in the CI build. |
Eh.. the test failure is not unrelated... |
@@ -153,7 +153,7 @@ public static function dataDeprecatedSniffsListDoesNotShowNeedsCsMode() | |||
return [ | |||
'Standard using deprecated sniffs; documentation is requested' => [ | |||
'standard' => __DIR__.'/ShowSniffDeprecationsTest.xml', | |||
'additionalArgs' => ['--generator=text'], | |||
'additionalArgs' => ['--generator=Text'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please undo this change. This is perfectly valid. Your PR needs a fix, not this unrelated test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh.. the test failure is not unrelated...
Indeed, I chose a poor word to describe what I meant.
Please undo this change. This is perfectly valid. Your PR needs a fix, not this unrelated test.
@jrfnl, just checking, did you check the commit message? Do you disagree with my assessment describing why I updated the test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not, but have now and I don't agree with your assessment.
The basic premise for the CLI arguments is that they should be handled case-insensitively, so text
is perfectly valid and should be accepted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But on master
, phpcs --standard=Generic --generator=text
does not work and throws a fatal error. Or maybe it throws a fatal error on Linux (case-sensitive OS) but not on Windows (case-insensitive OS)?
If that is the case, I failed to consider case-insensitive operating systems in this PR. I'm not sure what would be the best approach for this PR to accommodate this.
Maybe perform a case-insensitive check for the generator name when running on Windows and a case-sensitive check when running on other systems? What I don't like about this approach is that PHPCS would continue to behave differently depending on the OS.
Another option is to change PHPCS to ensure that it behaves consistently across different operating systems and handles the --generator
CLI argument case-insensitively.
The basic premise for the CLI arguments is that they should be handled case-insensitively
I was not aware of that and I can think of one other example of a CLI argument that is not case-insensitive when PHPCS is running on Linux: --standard=generic
. I'm not sure if there are other cases.
phpcs --generator=Text --standard=generic
ERROR: the "generic" coding standard is not installed. The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend and MyStandard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But on
master
,phpcs --standard=Generic --generator=text
does not work and throws a fatal error. Or maybe it throws a fatal error on Linux (case-sensitive OS) but not on Windows (case-insensitive OS)?
Exactly. It is currently (unintentionally) OS-dependent, but shouldn't be.
Another option is to change PHPCS to ensure that it behaves consistently across different operating systems and handles the
--generator
CLI argument case-insensitively.
IMO, that would be the correct thing to do.
The basic premise for the CLI arguments is that they should be handled case-insensitively
I was not aware of that and I can think of one other example of a CLI argument that is not case-insensitive when PHPCS is running on Linux:
--standard=generic
. I'm not sure if there are other cases.
That's outside the scope of this PR. Might be worth opening an issue to investigate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re: CLI and case-insensitive: squizlabs/PHP_CodeSniffer#1656 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the additional information. I will drop the commit that changed testDeprecatedSniffsListDoesNotShowNeedsCsMode()
and update this PR to ensure that the error displayed in Config::processLongArgument()
for invalid generator names treats the value of the --generator
argument case-insensitively.
Another option is to change PHPCS to ensure that it behaves consistently across different operating systems and handles the --generator CLI argument case-insensitively.
IMO, that would be the correct thing to do.
To implement this, I believe it will be necessary to change Runner::runPHPCS()
to load the correct generator class no matter what is the case of the passed generator argument. This is a separate change not directly related to #709. Do you prefer to review this change in this PR or a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think the case-(in)sensitively should be handled in the Runner
class instead of in the Config
class ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I did not consider normalizing the input in the Config
class when setting Config::generator
, and was thinking about doing that in the Runner
class.
To illustrate what I had in mind, assuming --generator=text
is passed, my plan was to do a case-insensitive check in the Config
class to see if the generator name passed is valid. Then, on the Runner
class the code normalizes the generator name (i.e, modifies the generator name to match the case of the desired file/class name).
After seeing your question, I realized that it makes sense to normalize the generator name in the Config
class, and that is probably what you had in mind. Is this correct?
I was also missing that Runner::runPHPCS()
creates an instance of Config
. Since I was missing that, I was worried about runPHPCS()
being called directly and attempting to instantiate a generator without the validation and normalization performed in the Config
class.
7141e6d
to
6bb661d
Compare
@jrfnl, I dropped the commit that changed |
There was a problem hiding this 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.
* | ||
* @var array<string, string> | ||
*/ | ||
private static $validGenerators = [ |
There was a problem hiding this comment.
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
?
* Note: once support for PHP < 5.6 is dropped, this property should be refactored into a class | ||
* constant. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Note: once support for PHP < 5.6 is dropped, this property should be refactored into a class | |
* constant. | |
* {@internal Once support for PHP < 5.6 is dropped, this property should be refactored into a class | |
* constant.} |
* - Keys: lowercase version of the generator name. | ||
* - Values: name of the generator PHP class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be part of the "long description" of the variable or part of the description of the @var
type ?
$lowerCaseGeneratorName = strtolower($generatorName); | ||
|
||
if (isset(self::$validGenerators[$lowerCaseGeneratorName]) === false) { | ||
$validOptions = implode(', ', array_values(self::$validGenerators)); |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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 " ?
if (isset(self::$validGenerators[$lowerCaseGeneratorName]) === false) { | ||
$validOptions = implode(', ', array_values(self::$validGenerators)); | ||
$error = sprintf( | ||
'ERROR: "%s" is not a valid generator. Valid options are: %s.'.PHP_EOL.PHP_EOL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a suggestion...
'ERROR: "%s" is not a valid generator. Valid options are: %s.'.PHP_EOL.PHP_EOL, | |
'ERROR: "%s" is not a valid generator. The following generators are supported: %s.'.PHP_EOL.PHP_EOL, |
@@ -23,37 +23,59 @@ final class GeneratorArgTest extends TestCase | |||
/** | |||
* Ensure that the generator property is set when the parameter is passed a valid value. | |||
* | |||
* @param string $generatorName Generator name. | |||
* @param string $argumentValue Generator name passed in the command line. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param string $argumentValue Generator name passed in the command line. | |
* @param string $argumentValue Generator name passed on the command line. |
* | ||
* @return array<int, array<string>> | ||
*/ | ||
public static function dataGeneratorNames() | ||
public static function dataValidGeneratorNames() | ||
{ | ||
return [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this array is now a little more involved, I think it would make it more straight-forward to maintain and to read the tests if the array included test case names + argument names.
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 thesrc/Generator/
directory:PHP_CodeSniffer/src/Runner.php
Lines 97 to 98 in 3d14d00
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
PR checklist