Skip to content

Commit 22ef98c

Browse files
freddenjrfnl
authored andcommitted
Handle @param when var passed by reference
1 parent cfb95cb commit 22ef98c

File tree

4 files changed

+198
-7
lines changed

4 files changed

+198
-7
lines changed

src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -547,24 +547,46 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart)
547547

548548
// Make sure the param name is correct.
549549
if (isset($realParams[$pos]) === true) {
550-
$realName = $realParams[$pos]['name'];
551-
if ($realName !== $param['var']) {
550+
$realName = $realParams[$pos]['name'];
551+
$paramVarName = $param['var'];
552+
553+
if ($param['var'][0] === '&') {
554+
// Even when passed by reference, the variable name in $realParams does not have
555+
// a leading '&'. This sniff will accept both '&$var' and '$var' in these cases.
556+
$paramVarName = substr($param['var'], 1);
557+
558+
// This makes sure that the 'MissingParamTag' check won't throw a false positive.
559+
$foundParams[(count($foundParams) - 1)] = $paramVarName;
560+
561+
if ($realParams[$pos]['pass_by_reference'] !== true && $realName === $paramVarName) {
562+
// Don't complain about this unless the param name is otherwise correct.
563+
$error = 'Doc comment for parameter %s is prefixed with "&" but parameter is not passed by reference';
564+
$code = 'ParamNameUnexpectedAmpersandPrefix';
565+
$data = [$paramVarName];
566+
567+
// We're not offering an auto-fix here because we can't tell if the docblock
568+
// is wrong, or the parameter should be passed by reference.
569+
$phpcsFile->addError($error, $param['tag'], $code, $data);
570+
}
571+
}
572+
573+
if ($realName !== $paramVarName) {
552574
$code = 'ParamNameNoMatch';
553575
$data = [
554-
$param['var'],
576+
$paramVarName,
555577
$realName,
556578
];
557579

558580
$error = 'Doc comment for parameter %s does not match ';
559-
if (strtolower($param['var']) === strtolower($realName)) {
581+
if (strtolower($paramVarName) === strtolower($realName)) {
560582
$error .= 'case of ';
561583
$code = 'ParamNameNoCaseMatch';
562584
}
563585

564586
$error .= 'actual variable name %s';
565587

566588
$phpcsFile->addError($error, $param['tag'], $code, $data);
567-
}
589+
}//end if
568590
} else if (substr($param['var'], -4) !== ',...') {
569591
// We must have an extra parameter comment.
570592
$error = 'Superfluous parameter comment';

src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,3 +1054,78 @@ function throwCommentOneLine() {}
10541054
* @return void
10551055
*/
10561056
function doublePipeFatalError(?stdClass $object) {}
1057+
1058+
/**
1059+
* Test for passing variables by reference
1060+
*
1061+
* This sniff treats the '&' as optional for parameters passed by reference, but
1062+
* forbidden for parameters which are not passed by reference.
1063+
*
1064+
* Because mismatches may be in either direction, we cannot auto-fix these.
1065+
*
1066+
* @param string $foo A string passed in by reference.
1067+
* @param string &$bar A string passed in by reference.
1068+
* @param string $baz A string NOT passed in by reference.
1069+
* @param string &$qux A string NOT passed in by reference.
1070+
* @param string &$case1 A string passed in by reference with a case mismatch.
1071+
* @param string &$CASE2 A string NOT passed in by reference, also with a case mismatch.
1072+
*
1073+
* @return void
1074+
*/
1075+
public function variablesPassedByReference(&$foo, &$bar, $baz, $qux, &$CASE1, $case2)
1076+
{
1077+
return;
1078+
}
1079+
1080+
/**
1081+
* Test for param tag containing ref, but param in declaration not being by ref.
1082+
*
1083+
* @param string &$foo This should be flagged as (only) ParamNameUnexpectedAmpersandPrefix.
1084+
* @param string &$bar This should be flagged as (only) ParamNameNoMatch.
1085+
* @param string &$baz This should be flagged as (only) ParamNameNoCaseMatch.
1086+
*
1087+
* @return void
1088+
*/
1089+
function passedByRefMismatch($foo, $bra, $BAZ) {
1090+
return;
1091+
}
1092+
1093+
/**
1094+
* Test variable case
1095+
*
1096+
* @param string $foo This parameter is lowercase.
1097+
* @param string $BAR This parameter is UPPERCASE.
1098+
* @param string $BazQux This parameter is TitleCase.
1099+
* @param string $corgeGrault This parameter is camelCase.
1100+
* @param string $GARPLY This parameter should be in lowercase.
1101+
* @param string $waldo This parameter should be in TitleCase.
1102+
* @param string $freD This parameter should be in UPPERCASE.
1103+
* @param string $PLUGH This parameter should be in TitleCase.
1104+
*
1105+
* @return void
1106+
*/
1107+
public function variableCaseTest(
1108+
$foo,
1109+
$BAR,
1110+
$BazQux,
1111+
$corgeGrault,
1112+
$garply,
1113+
$Waldo,
1114+
$FRED,
1115+
$PluGh
1116+
) {
1117+
return;
1118+
}
1119+
1120+
/**
1121+
* Test variable order mismatch
1122+
*
1123+
* @param string $foo This is the third parameter.
1124+
* @param string $bar This is the first parameter.
1125+
* @param string $baz This is the second parameter.
1126+
*
1127+
* @return void
1128+
*/
1129+
public function variableOrderMismatch($bar, $baz, $foo) {
1130+
return;
1131+
}

src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,3 +1054,78 @@ function throwCommentOneLine() {}
10541054
* @return void
10551055
*/
10561056
function doublePipeFatalError(?stdClass $object) {}
1057+
1058+
/**
1059+
* Test for passing variables by reference
1060+
*
1061+
* This sniff treats the '&' as optional for parameters passed by reference, but
1062+
* forbidden for parameters which are not passed by reference.
1063+
*
1064+
* Because mismatches may be in either direction, we cannot auto-fix these.
1065+
*
1066+
* @param string $foo A string passed in by reference.
1067+
* @param string &$bar A string passed in by reference.
1068+
* @param string $baz A string NOT passed in by reference.
1069+
* @param string &$qux A string NOT passed in by reference.
1070+
* @param string &$case1 A string passed in by reference with a case mismatch.
1071+
* @param string &$CASE2 A string NOT passed in by reference, also with a case mismatch.
1072+
*
1073+
* @return void
1074+
*/
1075+
public function variablesPassedByReference(&$foo, &$bar, $baz, $qux, &$CASE1, $case2)
1076+
{
1077+
return;
1078+
}
1079+
1080+
/**
1081+
* Test for param tag containing ref, but param in declaration not being by ref.
1082+
*
1083+
* @param string &$foo This should be flagged as (only) ParamNameUnexpectedAmpersandPrefix.
1084+
* @param string &$bar This should be flagged as (only) ParamNameNoMatch.
1085+
* @param string &$baz This should be flagged as (only) ParamNameNoCaseMatch.
1086+
*
1087+
* @return void
1088+
*/
1089+
function passedByRefMismatch($foo, $bra, $BAZ) {
1090+
return;
1091+
}
1092+
1093+
/**
1094+
* Test variable case
1095+
*
1096+
* @param string $foo This parameter is lowercase.
1097+
* @param string $BAR This parameter is UPPERCASE.
1098+
* @param string $BazQux This parameter is TitleCase.
1099+
* @param string $corgeGrault This parameter is camelCase.
1100+
* @param string $GARPLY This parameter should be in lowercase.
1101+
* @param string $waldo This parameter should be in TitleCase.
1102+
* @param string $freD This parameter should be in UPPERCASE.
1103+
* @param string $PLUGH This parameter should be in TitleCase.
1104+
*
1105+
* @return void
1106+
*/
1107+
public function variableCaseTest(
1108+
$foo,
1109+
$BAR,
1110+
$BazQux,
1111+
$corgeGrault,
1112+
$garply,
1113+
$Waldo,
1114+
$FRED,
1115+
$PluGh
1116+
) {
1117+
return;
1118+
}
1119+
1120+
/**
1121+
* Test variable order mismatch
1122+
*
1123+
* @param string $foo This is the third parameter.
1124+
* @param string $bar This is the first parameter.
1125+
* @param string $baz This is the second parameter.
1126+
*
1127+
* @return void
1128+
*/
1129+
public function variableOrderMismatch($bar, $baz, $foo) {
1130+
return;
1131+
}

src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ public function getErrorList()
5050
138 => 4,
5151
139 => 4,
5252
143 => 3,
53-
152 => 1,
54-
155 => 2,
53+
155 => 1,
5554
159 => 1,
5655
161 => 2,
5756
166 => 1,
@@ -126,6 +125,26 @@ public function getErrorList()
126125
1006 => 1,
127126
1029 => 1,
128127
1053 => 1,
128+
1058 => 2,
129+
1069 => 1,
130+
1070 => 1,
131+
1071 => 1,
132+
1075 => 6,
133+
1080 => 2,
134+
1083 => 1,
135+
1084 => 1,
136+
1085 => 1,
137+
1089 => 3,
138+
1093 => 4,
139+
1100 => 1,
140+
1101 => 1,
141+
1102 => 1,
142+
1103 => 1,
143+
1107 => 8,
144+
1123 => 1,
145+
1124 => 1,
146+
1125 => 1,
147+
1129 => 3,
129148
];
130149

131150
// Mixed type hints only work from PHP 8.0 onwards.

0 commit comments

Comments
 (0)