-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Handle @param
in docblock for variables passed by reference
#3813
Handle @param
in docblock for variables passed by reference
#3813
Conversation
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'm not sure what would be the right approach here.
Fixing it like you do is one way, but is the &
there actually wrong ?
An alternative way of looking at it would be to ltrim()
a potential &
from a param name before doing the name compare.
Not sure what is best. Maybe PSR19 can give some guidance ?
PSR-19 makes no mention of variables passed by reference. Based on this, I'll update this pull request to instead ignore this character and not auto-fix. |
b6ae58c
to
10066e3
Compare
@param
in docblock for variables passed by reference
75678d6
to
edf58e8
Compare
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.
@fredden Thanks for updating this PR! Reviewed in detail now.
While this is not a PSR-19 sniff (but a Squiz one), I agree that taking guidance from PSR-19 for how to handle this is the right call. Not sure how prominent the mention of PSR-19 in the inline comments need to be though considering this is not a PSR-19 sniff.
Regarding the if/else:
- The "passed by ref + has leading
&
in param tag" case is now special cased, which solves the original issue reported. ✅ - The "has no leading
&
in param tag" case is also handled correctly, whether passed by ref or not. ✅ - I'm just wondering about the "not passed by ref but has leading
&
in param tag" case. ❓
I agree that flagging a "not passed by ref but has leading &
in param tag" situation is a good thing as there is clearly a mismatch. I also agree that auto-fixing this may be risking.
I'm mostly just wondering whether this should get it's own error with error code as, as things are, the following errors are thrown:
1050 | ERROR | [ ] Doc comment for parameter "$qux" missing (Squiz.Commenting.FunctionComment.MissingParamTag)
1062 | ERROR | [ ] Doc comment for parameter &$qux does not match actual variable name $qux (Squiz.Commenting.FunctionComment.ParamNameNoMatch)
The first of which - IMO - is incorrect as the doc comment for $qux
is not missing, it just has a leading &
.
The second of which is unclear/imprecise - the variable name does in actual fact match - as it's not the actual variable name which is incorrect, but the leading ampersand.
Code style nitpick: I personally wouldn't use an if/else for this.
The "default" for $paramVarName
is known and needs no special handling:
$paramVarName = $param['var'];
if ($realParams[$pos]['pass_by_reference'] === true && $paramVarName[0] === '&') {
// ...
$paramVarName = substr($paramVarName, 1);
// ...
}
$paramVarName = $param['var']; | ||
} | ||
|
||
if ($realName !== $paramVarName) { | ||
$code = 'ParamNameNoMatch'; | ||
$data = [ | ||
$param['var'], |
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['var'], | |
$paramVarName, |
Extra test to see the issue & safeguard the fix:
* @param string &$case A string passed in by reference with a case mismatch.
...
public function variablesPassedByReference(&$foo, &$bar, $baz, $qux, &$CASE)
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 thought that case mismatches were already covered by tests, but I couldn't find any. Keeping this as $param['var']
(and not using $paramVarName
) here was intentional, but I can see now that the message can be confusing. I've adjusted the messaging (in 4171ba1) and added a set of tests (in 4f5641b) to cover @param
tags with case mismatches.
@jrfnl would you prefer the message to omit the &
completely?
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.
If I were making these changes, I'd keep the "param has leading & while not passed by ref" vs the "param name mismatch" checks completely separate as these are effectively checking two completely different things.
So, yes, I'd do the name compare in a way to disregard a potential leading &
completely.
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've had another look at this and completely separated out the ampersand/by-reference check. It will now trigger independently of the param name checks.
|
a0c54c6
to
605d788
Compare
Parameters in PHP are case-sensitive, so yes, case mismatches should IMO definitely be flagged. |
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.
@fredden Thanks for the updates. IMO, there is one more tweak needed.
// This makes sure that the 'MissingParamTag' check won't throw a false positive. | ||
$foundParams[(count($foundParams) - 1)] = $paramVarName; | ||
|
||
if ($realParams[$pos]['pass_by_reference'] !== true) { |
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.
if ($realParams[$pos]['pass_by_reference'] !== true) { | |
if ($realName === $paramVarName && $realParams[$pos]['pass_by_reference'] !== true) { |
Extra tests to verify why I'm suggesting this change:
/**
* Test for param tag containing ref, but param in declaration not being by ref.
*
* @param string &$foo This should be flagged as ParamNameUnexpectedAmpersandPrefix.
* @param string &$bar This should be flagged as ParamNameNoMatch.
* @param string &$baz This should be flagged as ParamNameNoCaseMatch.
*
* @return void
*/
function passedByRefMismatch($foo, $bra, $BAZ) {
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.
This change seems fair. I had considered doing this but decided against it at the time. The reasoning was that if the variable name was incorrect and had a rogue leading ampersand, that both faults would be flagged. With the suggested change (which I've committed in 28ed6ae), users will get one fault identified at a time, so fixing one fault won't make all errors go away, but instead will make the error message change. I can see how having two errors is less desirable, especially in the case where the param tags are out of order and changing the order alone would fix all errors.
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.
Good points and I agree that generally speaking errors shouldn't hide behind each other, but in this case, if the variable name doesn't match, the information about whether or not the variable is passed by reference from the function signature is just plain unreliable, which is why I suggested the change.
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 your time & patience on this one @jrfnl. I appreciate the feedback etc. |
@fredden Would you mind rebasing this PR (and possibly squashing the commits) to get it past the merge conflict ? |
Yes, no problem. I'll look at this today. |
1b973a0
to
84621dd
Compare
FYI: this fix is included in today's PHP_CodeSniffer 3.8.0 release. As per #3932, development on PHP_CodeSniffer will continue in the PHPCSStandards/PHP_CodeSniffer repository. If you want to stay informed, you may want to start "watching" that repo (or watching releases from that repo). |
This started as an auto-fix to remove ampersands from
@param
tags in docblocks withinSquiz.Commenting.FunctionComment
. This has evolved into "handle@param
tags for variables passed by reference." We are also increasing test coverage of related-but-not-changed behaviour.