diff --git a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc index 55d1a06ab8..ac82c6814e 100644 --- a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc +++ b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc @@ -26,3 +26,18 @@ if ($foo) { $this->foo() ->bar() ->baz(); + +// https://github.com/squizlabs/PHP_CodeSniffer/issues/2078#issuecomment-401641650 +// See also PSR2.Methods.FunctionCallSignature +$repository->foo() + ->bar( + function () { + return true; + } + ); +$repository->foo() + ->bar( + function () { + return true; + } + ); diff --git a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed index e9ae5ff392..f8d242d217 100644 --- a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed +++ b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed @@ -26,3 +26,18 @@ if ($foo) { $this->foo() ->bar() ->baz(); + +// https://github.com/squizlabs/PHP_CodeSniffer/issues/2078#issuecomment-401641650 +// See also PSR2.Methods.FunctionCallSignature +$repository->foo() + ->bar( + function () { + return true; + } + ); +$repository->foo() + ->bar( + function () { + return true; + } + ); diff --git a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php index 23905fdadc..9ba236ba9f 100644 --- a/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php +++ b/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php @@ -79,6 +79,9 @@ public function getErrorList($testFile='ScopeIndentUnitTest.inc') 6 => 1, 7 => 1, 10 => 1, + 40 => 1, + 41 => 1, + 42 => 1, ]; } diff --git a/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php b/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php index 30e0f67aea..fa6c09d66e 100644 --- a/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php +++ b/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php @@ -376,30 +376,16 @@ public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $ // at a tab stop. Without this, the function will be indented a further // $indent spaces to the right. $functionIndent = (int) (floor($foundFunctionIndent / $this->indent) * $this->indent); - $adjustment = 0; + $adjustment = ($functionIndent - $foundFunctionIndent); if ($foundFunctionIndent !== $functionIndent) { - $error = 'Opening statement of multi-line function call not indented correctly; expected %s spaces but found %s'; - $data = [ + $this->complainOpenStatementWrongIndent( + $phpcsFile, + $first, + $tokens, $functionIndent, - $foundFunctionIndent, - ]; - - $fix = $phpcsFile->addFixableError($error, $first, 'OpeningIndent', $data); - if ($fix === true) { - // Set adjustment for use later to determine whether argument indentation is correct when fixing. - $adjustment = ($functionIndent - $foundFunctionIndent); - - $padding = str_repeat(' ', $functionIndent); - if ($foundFunctionIndent === 0) { - $phpcsFile->fixer->addContentBefore($first, $padding); - } else if ($tokens[$first]['code'] === T_INLINE_HTML) { - $newContent = $padding.ltrim($tokens[$first]['content']); - $phpcsFile->fixer->replaceToken($first, $newContent); - } else { - $phpcsFile->fixer->replaceToken(($first - 1), $padding); - } - } + $foundFunctionIndent + ); }//end if $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); @@ -465,7 +451,7 @@ public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $ $i--; } - for ($i; $i < $closeBracket; $i++) { + for (; $i < $closeBracket; $i++) { if ($i > $argStart && $i < $argEnd) { $inArg = true; } else { @@ -545,10 +531,34 @@ public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $ $foundIndent = $tokens[$i]['length']; } - if ($foundIndent < $expectedIndent - || ($inArg === false - && $expectedIndent !== $foundIndent) - ) { + $indentCorrect = true; + + if ($foundIndent < $expectedIndent) { + $indentCorrect = false; + } else if ($inArg === false && $expectedIndent !== $foundIndent) { + $indentCorrect = false; + + // It is permitted to indent chains further than one tab stop to + // align vertically with the previous method call. + if ($i === ($closeBracket - 1)) { + if ($foundIndent === $foundFunctionIndent) { + // This is the closing paren; it lines up vertically with the opening paren. + $indentCorrect = true; + } + } else { + if ($foundIndent === ($tokens[$openBracket]['column'] - 1)) { + // This is a parameter; it lines up vertically with the opening paren. + $indentCorrect = true; + } + + if ($foundIndent === ($foundFunctionIndent + ($this->indent))) { + // This is a parameter; it is indented one more step than the function call around it. + $indentCorrect = true; + } + } + }//end if + + if ($indentCorrect === false) { $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s'; $data = [ $expectedIndent, @@ -631,4 +641,51 @@ public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $ }//end processMultiLineCall() + /** + * Add a complaint (and auto-fix) if the function indent is 'wrong'. + * + * @param File $phpcsFile The file being scanned. + * @param int $first Pointer to the first empty token on this line. + * @param array $tokens The stack of tokens that make up the file. + * @param int $functionIndent The expected indent for this function definition. + * @param int $foundFunctionIndent The actual indent for this function definition. + * + * @return void + */ + protected function complainOpenStatementWrongIndent( + $phpcsFile, + $first, + $tokens, + $functionIndent, + $foundFunctionIndent + ) { + if ($foundFunctionIndent === $functionIndent) { + return; + } + + $error = 'Opening statement of multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $functionIndent, + $foundFunctionIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'OpeningIndent', $data); + if ($fix !== true) { + return; + } + + $padding = str_repeat(' ', $functionIndent); + + if ($foundFunctionIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else if ($tokens[$first]['code'] === T_INLINE_HTML) { + $newContent = $padding.ltrim($tokens[$first]['content']); + $phpcsFile->fixer->replaceToken($first, $newContent); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + + }//end complainOpenStatementWrongIndent() + + }//end class diff --git a/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php b/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php index 4e0eeffb20..12b5b09877 100644 --- a/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php +++ b/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php @@ -69,7 +69,7 @@ public function getErrorList($testFile='FunctionCallSignatureUnitTest.inc') 82 => 1, 93 => 1, 100 => 1, - 106 => 2, + 106 => 1, 119 => 1, 120 => 1, 129 => 1, @@ -98,15 +98,9 @@ public function getErrorList($testFile='FunctionCallSignatureUnitTest.inc') 346 => 2, 353 => 1, 354 => 1, - 355 => 2, + 355 => 1, 377 => 1, - 378 => 1, - 379 => 1, - 380 => 1, 385 => 1, - 386 => 1, - 387 => 1, - 388 => 1, 393 => 1, 394 => 1, 395 => 1, @@ -135,7 +129,6 @@ public function getErrorList($testFile='FunctionCallSignatureUnitTest.inc') 567 => 1, 568 => 1, 573 => 1, - 574 => 1, ]; }//end getErrorList() diff --git a/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php b/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php index cee18cacde..35fc51cbd2 100644 --- a/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php +++ b/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php @@ -25,7 +25,7 @@ class FunctionCallSignatureSniff extends PEARFunctionCallSignatureSniff /** - * Processes single-line calls. + * Determine if this is a multi-line function call. * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token @@ -76,4 +76,26 @@ public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $token }//end isMultiLineCall() + /** + * No-op; this rule does not apply to PSR-2. + * + * @param File $phpcsFile The file being scanned. + * @param int $first Pointer to the first empty token on this line. + * @param array $tokens The stack of tokens that make up the file. + * @param int $functionIndent The expected indent for this function definition. + * @param int $foundFunctionIndent The actual indent for this function definition. + * + * @return void + */ + protected function complainOpenStatementWrongIndent( + $phpcsFile, + $first, + $tokens, + $functionIndent, + $foundFunctionIndent + ) { + + }//end complainOpenStatementWrongIndent() + + }//end class diff --git a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc index 1ca477d054..c74b0b87b9 100644 --- a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc +++ b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc @@ -265,3 +265,18 @@ array_fill_keys( ), value: true, ); // phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false + +// https://github.com/squizlabs/PHP_CodeSniffer/issues/2078#issuecomment-401641650 +// This sniff should accept both of these styles. Generic.WhiteSpace.ScopeIndent can complain & fix this if enabled. +$repository->foo() + ->bar( + function () { + return true; + } + ); +$repository->foo() + ->bar( + function () { + return true; + } + ); diff --git a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed index dc383ed2a7..e553146479 100644 --- a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed +++ b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed @@ -281,3 +281,18 @@ array_fill_keys( ), value: true, ); // phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false + +// https://github.com/squizlabs/PHP_CodeSniffer/issues/2078#issuecomment-401641650 +// This sniff should accept both of these styles. Generic.WhiteSpace.ScopeIndent can complain & fix this if enabled. +$repository->foo() + ->bar( + function () { + return true; + } + ); +$repository->foo() + ->bar( + function () { + return true; + } + ); diff --git a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php index 7f6ce1f959..06c3109794 100644 --- a/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php +++ b/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php @@ -52,12 +52,12 @@ public function getErrorList() 187 => 1, 194 => 3, 199 => 1, - 200 => 2, + 200 => 1, 202 => 1, 203 => 1, 210 => 2, 211 => 1, - 212 => 2, + 212 => 1, 217 => 1, 218 => 1, 227 => 1, diff --git a/src/Standards/PSR2/ruleset.xml b/src/Standards/PSR2/ruleset.xml index ba5bd4e0ba..190502de61 100644 --- a/src/Standards/PSR2/ruleset.xml +++ b/src/Standards/PSR2/ruleset.xml @@ -151,9 +151,6 @@ 0 - - 0 -