-
-
Notifications
You must be signed in to change notification settings - Fork 57
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
Generic/CallTimePassByReference: support anonymous classes and improve code coverage #394
Generic/CallTimePassByReference: support anonymous classes and improve code coverage #394
Conversation
The minimum supported PHP version of this codebase is completely unrelated to the supported PHP version(s) of the code base under scan, so that's never a valid argument.
That's not the only usecase, it is also useful to prevent new issues from entering a codebase, which could just be a simple oversight from whomever wrote the code or it could be that the person who wrote the code is not that familiar with PHP. More than anything, I see no reason to remove it as long as there are people who use the sniff. |
Actually, AFAICS the |
Did you do a |
Thanks for clarifying that the sniff should not be deprecated and providing good reasons for that.
I assumed this use case was not relevant since the call-time pass-by-reference causes a parse error in PHP >= 5.4 (I'm saying this just to share my thought process, and not to continue arguing for the deprecation of this sniff).
Good point. I added a new commit removing
What you have in mind is that the sniff should be triggered by the code below? $anon = new class(&$a) {}; I guess that the rationale is that, even if this code is not valid in any version of PHP (no version that supports both call-time pass-by-reference and anonymous class), it is still useful for users if the sniff flags this code to prevent new issues from entering the codebase?
Yes, I mentioned it in the commit message but I could have mentioned it in the PR description: The removed check was added in this commit that added defensive code to protect against syntax errors to a few sniffs: 0e42098 It is not clear to me by checking the commit if there is a valid case that this code is protecting against. |
Well, unfortunately the fast majority of projects do not have a CI process set up or only a limited one (only PHPCS), so the chances of this not being caught by linting/tests can be pretty high, which means the fatal would bring down production.
That test is sufficient for class declarations, but you mentioned other OO declarations as the trigger for your original remark, so maybe tests should be added to guard against false positives for traits/enums/interfaces declarations ? And yes, also to guard against false negatives for anonymous classes.
Whether the syntaxes are mutually exclusive is irrelevant. This sniff should do what its purpose is: detect call time pass by reference and even when used in an anonymous class declaration, it is still call time pass by reference. On that note: can you think of situations where the
Please always add all relevant information in the PR description. Don't make me go searching for things.
Did you check the issue the commit references for the bug report ? |
I added a new commit with tests to guard against false positives for traits/enums/interfaces. I used the test for classes as a reference.
The only other situation I could think of is class instantiation. So, I added a few tests to cover that in the same commit I mentioned above.
In a separate commit, I changed the sniff to flag call-time pass-by-reference in anonymous classes and updated the PR title and description to reflect that. The implementation was fairly simple. I hope I'm not missing something.
Sure, and I'm sorry for doing it this time.
Yes and no. The first time I checked, I failed to notice that I was checking the wrong issue. The commit message points to issue 316 in this repository. I didn't see the connection between the two and thought I had reached a dead end. Only now, I realized that I should have checked issue 316 in the old repository: squizlabs/PHP_CodeSniffer#316. The issue mentions two code snippets that would cause PHPCS to generate PHP notices. Unfortunately, one of the snippets is not available anymore. I confirmed that the sniff correctly handles the code snippet that is still available even if the condition that I removed. |
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.
Hi @rodrigoprimo Looking good!
Thanks for making these changes.
There is one additional syntax I can think of which this sniff is currently not picking up on, while it probably should be:
new static(&a);
(and the same with self/parent)
Not a blocker for this PR, but probably a nice to have for a follow-up PR. Would you be willing to work on that ?
231c15f
to
7b483df
Compare
Doing this to be able to create tests with syntax errors on separate files.
This commit fixes a non-problematic bug when there are only empty tokens after a variable or string token and nothing else. Before this commit, the code would search for the next non-empty token after a variable or string token. It would assume that there would always be such a token and it would check if this token is a open parenthesis token. It is possible that there are no tokens or only empty tokens after the variable or string token when live coding. This assumption would not cause any problems because when checking if `$tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS`, `$openBracket` would be `false`, and then PHP would check for the first element in the $tokens array. The first token can never be a T_OPEN_PARENTHESIS and so the code would bail early as expected. This commit adds a `$openBracket === false` check to bail early as well to make it clear that `$openBracket` can be false.
Removes a condition that checks if `nested_parenthesis` property of the variable or short syntax array is not set. As far as I can check, this condition can never be true. A few lines above, we are already checking for the presence of opening and closing parentheses and the while loop is limited to T_VARIABLE and T_OPEN_SHORT_ARRAY inside the parentheses. Since it is limited to tokens inside the parentheses, `nested_parenthesis` will always be set. The removed check was added in this commit that added defensive code to protect against syntax errors to a few sniffs: PHPCSStandards@0e42098
This commit removes the `|| $prevCode === T_CLASS` condition from a if statement. The removed check is not necessary as the next thing the sniff does is to check for an opening parenthesis after `$stackPtr` and bow out if one is not found. Class definitions will never have an opening parentesis after its name. Anonymous classes do have a opening parenthesis after the T_CLASS token. They are currently not handled correctly by this sniff and this will be addressed on another commit.
This commit changes the sniff to flag call-time pass-by-reference arguments when instantiating an anonymous class.
7b483df
to
b91a18b
Compare
Rebased (to get passed the merge conflict) and squashed a few commits together, no functional changes. Will merge once the build passes now. |
Yes, I will prepare a PR to change the sniff to support the cases that you mentioned. |
Description
This PR changes the Generic.Functions.CallTimePassByReference sniff to flag call-time pass-by-reference when instantiating an anonymous class. It also fixes a non-problematic bug, improves code coverage and removes an unreachable condition.
Regarding the unreachable condition, I worry that I might be missing something and the condition is actually reachable. I can drop the commit if during the review you are not sure if it is unreachable or not.
While working on this PR, I could see a few potential improvements to this sniff (like bailing early for all OO scope tokens and not just classes, but there is something that I want to check before implementing those improvements (likely on a separate PR). PHPCS supports PHP >= 5.4. Call-time pass-by-reference was removed in PHP 5.4. This means that this sniff checks for syntax that causes a fatal error in all supported PHP versions and thus I wonder if it should be deprecated? The only use case that I can think of for this sniff is if someone decides to modernize PHP < 5.4 code and I'm unsure if this is a reason to keep this sniff or not.
Suggested changelog entry
Generic.Functions.CallTimePassByReference: fixed non-problematic bug when
$openBracket
is falseGeneric.Functions.CallTimePassByReference: flag call-time pass-by-reference when instantiating an anonymous class
Related issues/external references
Part of #146
Types of changes
PR checklist