Skip to content

Commit 1a2e643

Browse files
committed
Merge remote-tracking branch 'upstream/master' into whitespace-incompatibility
2 parents 58512dc + 354b4c5 commit 1a2e643

File tree

9 files changed

+286
-54
lines changed

9 files changed

+286
-54
lines changed

package.xml

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
1717
<date>2022-06-18</date>
1818
<time>17:20:00</time>
1919
<version>
20-
<release>3.7.2</release>
21-
<api>3.7.2</api>
20+
<release>3.8.0</release>
21+
<api>3.8.0</api>
2222
</version>
2323
<stability>
2424
<release>stable</release>
@@ -41,11 +41,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
4141
-- Existing code will continue to work but will throw a deprecation error
4242
-- The backwards compatiblity layer will be removed in PHPCS 4.0
4343
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
44-
- Newer versions of Composer will now suggest installing PHPCS using require-dev instead of require
45-
-- Thanks to Gary Jones (@GaryJones) for the patch
46-
- A custom Out Of Memory error will now be shown if PHPCS or PHPCBF run out of memory during a run
47-
-- Error message provides actionable information about how to fix the problem and ensures the error is not silent
48-
-- Thanks to Juliette Reinders Folmer (@jrfnl) and Alain Schlesser (@schlessera) for the patch
4944
- When using auto report width (the default) a value of 80 columns will be used if an auto width cannot be determined
5045
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
5146
- Sniff error messages are now more informative to help bugs get reported to the correct project
@@ -64,41 +59,23 @@ http://pear.php.net/dtd/package-2.0.xsd">
6459
-- Squiz.Commenting.FileComment
6560
-- Squiz.Commenting.InlineComment
6661
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
67-
- Generic.PHP.LowerCaseType sniff now correctly examines types inside arrow functions
68-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
6962
- PSR2.Classes.PropertyDeclaration now enforces that the readonly modifier comes after the visibility modifier
7063
- PSR2 and PSR12 do not have documented rules for this as they pre-date the readonly modifier
7164
- PSR-PER has been used to confirm the order of this keyword so it can be applied to PSR2 and PSR12 correctly
7265
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
73-
- Squiz.Formatting.OperatorBracket no longer reports false positives in match() structures
66+
- Squiz.Commenting.FunctionComment: new ParamNameUnexpectedAmpersandPrefix error for parameters annotated as passed by reference while the parameter is not passed by reference
67+
-- Thanks to Dan Wallis (@fredden) for the patch
68+
- Squiz.PHP.InnerFunctions sniff no longer reports on OO methods for OO structures declared within a function or closure
69+
-- Thanks to @Daimona for the patch
7470
- Documentation has been added for the following sniffs:
7571
-- PSR2.Files.ClosingTag
7672
-- PSR2.Methods.FunctionCallSignature
7773
-- PSR2.Methods.FunctionClosingBrace
7874
-- Thanks to Atsushi Okui (@blue32a) for the patch
7975
- Fixed bug #3557 : Squiz.Arrays.ArrayDeclaration will now ignore PHP 7.4 array unpacking when determining whether an array is associative
8076
-- Thanks to Volker Dusch (@edorian) for the patch
81-
- Fixed bug #3616 : Squiz.PHP.DisallowComparisonAssignment false positive for PHP 8 match expression
82-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
83-
- Fixed bug #3618 : Generic.WhiteSpace.ArbitraryParenthesesSpacing false positive for return new parent()
84-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
85-
- Fixed bug #3632 : Short list not tokenized correctly in control structures without braces
86-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
87-
- Fixed bug #3639 : Tokenizer not applying tab replacement to heredoc/nowdoc closers
88-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
89-
- Fixed bug #3640 : Generic.WhiteSpace.DisallowTabIndent not reporting errors for PHP 7.3 flexible heredoc/nowdoc syntax
90-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
91-
- Fixed bug #3645 : PHPCS can show 0 exit code when running in parallel even if child process has fatal error
92-
-- Thanks to Alex Panshin (@enl) for the patch
93-
- Fixed bug #3653 : False positives for match() in OperatorSpacingSniff
94-
-- Thanks to Jaroslav Hanslík (@kukulich) for the patch
95-
- Fixed bug #3666 : PEAR.Functions.FunctionCallSignature incorrect indent fix when checking mixed HTML/PHP files
96-
- Fixed bug #3668 : PSR12.Classes.ClassInstantiation.MissingParentheses false positive when instantiating parent classes
97-
-- Similar issues also fixed in Generic.Functions.FunctionCallArgumentSpacing and Squiz.Formatting.OperatorBracket
98-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
99-
- Fixed bug #3672 : Incorrect ScopeIndent.IncorrectExact report for match inside array literal
100-
- Fixed bug #3694 : Generic.WhiteSpace.SpreadOperatorSpacingAfter does not ignore spread operator in PHP 8.1 first class callables
101-
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
77+
- Fixed bug #3717 : Squiz.Commenting.FunctionComment: fixed false positive for InvalidNoReturn when type is never
78+
-- Thanks to Choraimy Kroonstuiver (@axlon) for the patch
10279
- Fixed bug #3722 : Potential "Uninitialized string offset 1" in octal notation backfill
10380
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
10481
- Fixed bug #3728 : PHP 8.2 | PSR1/SideEffects: allow for readonly classes
@@ -109,7 +86,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
10986
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
11087
- Fixed bug #3779 : Squiz/LowercasePHPFunctions + Generic/ForbiddenFunctions: bug fix for class names in attributes
11188
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
112-
- Fixed bug #3785 : Squiz/FunctionComment: potential "Uninitialized string offset 0" when a type contains a duplicate pipe symbol
89+
- Fixed bug #3785 : Squiz.Commenting.FunctionComment: potential "Uninitialized string offset 0" when a type contains a duplicate pipe symbol
11390
-- Thanks to Dan Wallis (@fredden) for the patch
11491
- Fixed bug #3787 : PEAR/Squiz/[MultiLine]FunctionDeclaration: allow for PHP 8.1 new in initializers
11592
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
@@ -121,6 +98,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
12198
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
12299
- Fixed bug #3805 : Generic/FunctionCallArgumentSpacing: prevent fixer conflict over PHP 7.3+ trailing comma's in function calls
123100
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
101+
- Fixed bug #3806 : Squiz.PHP.InnerFunctions sniff now correctly reports inner functions declared within a closure
102+
-- Thanks to @Daimona for the patch
103+
- Fixed bug #3813 : Squiz.Commenting.FunctionComment: false positive for parameter name mismatch on parameters annotated as passed by reference
104+
-- Thanks to Dan Wallis (@fredden) for the patch
124105
- Fixed bug #3816 : PSR12/FileHeader: bug fix - false positives on PHP 8.2+ readonly classes
125106
-- Thanks to Juliette Reinders Folmer (@jrfnl) for the patch
126107
</notes>

src/Config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class Config
8080
*
8181
* @var string
8282
*/
83-
const VERSION = '3.7.2';
83+
const VERSION = '3.8.0';
8484

8585
/**
8686
* Package stability; either stable, beta or alpha.

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

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,12 @@ protected function processReturn(File $phpcsFile, $stackPtr, $commentStart)
143143
}
144144
}
145145
}//end if
146-
} else if ($returnType !== 'mixed' && in_array('void', $typeNames, true) === false) {
147-
// If return type is not void, there needs to be a return statement
148-
// somewhere in the function that returns something.
146+
} else if ($returnType !== 'mixed'
147+
&& $returnType !== 'never'
148+
&& in_array('void', $typeNames, true) === false
149+
) {
150+
// If return type is not void, never, or mixed, there needs to be a
151+
// return statement somewhere in the function that returns something.
149152
if (isset($tokens[$stackPtr]['scope_closer']) === true) {
150153
$endToken = $tokens[$stackPtr]['scope_closer'];
151154
for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) {
@@ -555,24 +558,46 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart)
555558

556559
// Make sure the param name is correct.
557560
if (isset($realParams[$pos]) === true) {
558-
$realName = $realParams[$pos]['name'];
559-
if ($realName !== $param['var']) {
561+
$realName = $realParams[$pos]['name'];
562+
$paramVarName = $param['var'];
563+
564+
if ($param['var'][0] === '&') {
565+
// Even when passed by reference, the variable name in $realParams does not have
566+
// a leading '&'. This sniff will accept both '&$var' and '$var' in these cases.
567+
$paramVarName = substr($param['var'], 1);
568+
569+
// This makes sure that the 'MissingParamTag' check won't throw a false positive.
570+
$foundParams[(count($foundParams) - 1)] = $paramVarName;
571+
572+
if ($realParams[$pos]['pass_by_reference'] !== true && $realName === $paramVarName) {
573+
// Don't complain about this unless the param name is otherwise correct.
574+
$error = 'Doc comment for parameter %s is prefixed with "&" but parameter is not passed by reference';
575+
$code = 'ParamNameUnexpectedAmpersandPrefix';
576+
$data = [$paramVarName];
577+
578+
// We're not offering an auto-fix here because we can't tell if the docblock
579+
// is wrong, or the parameter should be passed by reference.
580+
$phpcsFile->addError($error, $param['tag'], $code, $data);
581+
}
582+
}
583+
584+
if ($realName !== $paramVarName) {
560585
$code = 'ParamNameNoMatch';
561586
$data = [
562-
$param['var'],
587+
$paramVarName,
563588
$realName,
564589
];
565590

566591
$error = 'Doc comment for parameter %s does not match ';
567-
if (strtolower($param['var']) === strtolower($realName)) {
592+
if (strtolower($paramVarName) === strtolower($realName)) {
568593
$error .= 'case of ';
569594
$code = 'ParamNameNoCaseMatch';
570595
}
571596

572597
$error .= 'actual variable name %s';
573598

574599
$phpcsFile->addError($error, $param['tag'], $code, $data);
575-
}
600+
}//end if
576601
} else if (substr($param['var'], -4) !== ',...') {
577602
// We must have an extra parameter comment.
578603
$error = 'Superfluous parameter comment';

src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use PHP_CodeSniffer\Files\File;
1313
use PHP_CodeSniffer\Sniffs\Sniff;
14+
use PHP_CodeSniffer\Util\Tokens;
1415

1516
class InnerFunctionsSniff implements Sniff
1617
{
@@ -41,21 +42,28 @@ public function process(File $phpcsFile, $stackPtr)
4142
{
4243
$tokens = $phpcsFile->getTokens();
4344

44-
$function = $phpcsFile->getCondition($stackPtr, T_FUNCTION);
45-
if ($function === false) {
46-
// Not a nested function.
45+
if (isset($tokens[$stackPtr]['conditions']) === false) {
4746
return;
4847
}
4948

50-
$class = $phpcsFile->getCondition($stackPtr, T_ANON_CLASS, false);
51-
if ($class !== false && $class > $function) {
52-
// Ignore methods in anon classes.
53-
return;
49+
$conditions = $tokens[$stackPtr]['conditions'];
50+
$reversedConditions = array_reverse($conditions, true);
51+
52+
$outerFuncToken = null;
53+
foreach ($reversedConditions as $condToken => $condition) {
54+
if ($condition === T_FUNCTION || $condition === T_CLOSURE) {
55+
$outerFuncToken = $condToken;
56+
break;
57+
}
58+
59+
if (\array_key_exists($condition, Tokens::$ooScopeTokens) === true) {
60+
// Ignore methods in OOP structures defined within functions.
61+
return;
62+
}
5463
}
5564

56-
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
57-
if ($tokens[$prev]['code'] === T_EQUAL) {
58-
// Ignore closures.
65+
if ($outerFuncToken === null) {
66+
// Not a nested function.
5967
return;
6068
}
6169

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,3 +1054,83 @@ 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+
}
1132+
1133+
/**
1134+
* @return never
1135+
*/
1136+
function foo() {}

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,3 +1054,83 @@ 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+
}
1132+
1133+
/**
1134+
* @return never
1135+
*/
1136+
function foo() {}

0 commit comments

Comments
 (0)