Skip to content

Commit 3f126c3

Browse files
committed
PEAR/FunctionDeclaration: examine arrow function declarations
PHP 7.4 arrow functions were not yet being taken into account for this sniff. Fixed now. Includes unit tests.
1 parent b860f75 commit 3f126c3

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php

+41-12
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public function register()
4646
return [
4747
T_FUNCTION,
4848
T_CLOSURE,
49+
T_FN,
4950
];
5051

5152
}//end register()
@@ -75,7 +76,9 @@ public function process(File $phpcsFile, $stackPtr)
7576
$openBracket = $tokens[$stackPtr]['parenthesis_opener'];
7677
$closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
7778

78-
if (strtolower($tokens[$stackPtr]['content']) === 'function') {
79+
if (strtolower($tokens[$stackPtr]['content']) === 'function'
80+
|| strtolower($tokens[$stackPtr]['content']) === 'fn'
81+
) {
7982
// Must be one space after the FUNCTION keyword.
8083
if ($tokens[($stackPtr + 1)]['content'] === $phpcsFile->eolChar) {
8184
$spaces = 'newline';
@@ -86,9 +89,13 @@ public function process(File $phpcsFile, $stackPtr)
8689
}
8790

8891
if ($spaces !== 1) {
89-
$error = 'Expected 1 space after FUNCTION keyword; %s found';
90-
$data = [$spaces];
91-
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterFunction', $data);
92+
$error = 'Expected 1 space after %s keyword; %s found';
93+
$data = [
94+
strtoupper($tokens[$stackPtr]['content']),
95+
$spaces,
96+
];
97+
98+
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterFunction', $data);
9299
if ($fix === true) {
93100
if ($spaces === 0) {
94101
$phpcsFile->fixer->addContent($stackPtr, ' ');
@@ -99,9 +106,9 @@ public function process(File $phpcsFile, $stackPtr)
99106
}
100107
}//end if
101108

102-
// Must be no space before the opening parenthesis. For closures, this is
103-
// enforced by the previous check because there is no content between the keywords
104-
// and the opening parenthesis.
109+
// Must be no space before the opening parenthesis. For closures and arrow functions,
110+
// this is enforced by the previous check because there is no content between
111+
// the keywords and the opening parenthesis.
105112
// Unfinished closures are tokenized as T_FUNCTION however, and can be excluded
106113
// by checking for the scope_opener.
107114
if ($tokens[$stackPtr]['code'] === T_FUNCTION
@@ -257,6 +264,10 @@ public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tok
257264
*/
258265
public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens)
259266
{
267+
if ($tokens[$stackPtr]['code'] === T_FN) {
268+
return;
269+
}
270+
260271
if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
261272
$sniff = new OpeningFunctionBraceKernighanRitchieSniff();
262273
} else {
@@ -300,12 +311,20 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
300311
// The opening brace needs to be one space away from the closing parenthesis.
301312
$opener = $tokens[$stackPtr]['scope_opener'];
302313
if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) {
303-
$error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line';
304-
$fix = $phpcsFile->addFixableError($error, $opener, 'NewlineBeforeOpenBrace');
314+
$error = 'The closing parenthesis and the %s of a multi-line function declaration must be on the same line';
315+
$code = 'NewlineBeforeOpenBrace';
316+
$data = ['opening brace'];
317+
318+
if ($tokens[$stackPtr]['code'] === T_FN) {
319+
$code = 'NewlineBeforeArrow';
320+
$data = ['arrow'];
321+
}
322+
323+
$fix = $phpcsFile->addFixableError($error, $opener, $code, $data);
305324
if ($fix === true) {
306325
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true);
307326
$phpcsFile->fixer->beginChangeset();
308-
$phpcsFile->fixer->addContent($prev, ' {');
327+
$phpcsFile->fixer->addContent($prev, ' '.$tokens[$opener]['content']);
309328

310329
// If the opener is on a line by itself, removing it will create
311330
// an empty line, so just remove the entire line instead.
@@ -340,8 +359,18 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
340359
}
341360

342361
if ($length !== 1) {
343-
$error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found %s spaces';
344-
$fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]);
362+
$error = 'There must be a single space between the closing parenthesis and the %s of a multi-line function declaration; found %s spaces';
363+
$code = 'SpaceBeforeOpenBrace';
364+
$data = ['opening brace'];
365+
366+
if ($tokens[$stackPtr]['code'] === T_FN) {
367+
$code = 'SpaceBeforeArrow';
368+
$data = ['arrow'];
369+
}
370+
371+
$data[] = $length;
372+
373+
$fix = $phpcsFile->addFixableError($error, ($opener - 1), $code, $data);
345374
if ($fix === true) {
346375
if ($length === 0) {
347376
$phpcsFile->fixer->addContentBefore($opener, ' ');

src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc

+21
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,24 @@ class ConstructorPropertyPromotionMultiLineAttributesIncorrectIndent
418418
// Do something.
419419
}
420420
}
421+
422+
$arrowNoArgs = fn () => $retrievedfromscope;
423+
424+
$arrowSingleLineArgs = fn (Type $param1, int $param2, string $param3): \ReturnType => $retrievedfromscope;
425+
426+
$arrowMultiLineArgs = fn (
427+
$longVar1,
428+
$longerVar2,
429+
&...$muchLongerVar3
430+
) => $longVar1;
431+
432+
$arrowNoArgs = fn( )
433+
=> $retrievedfromscope;
434+
435+
$arrowSingleLineArgs = fn( Type $param1 , int $param2, string $param3
436+
) : \ReturnType => $retrievedfromscope;
437+
438+
$arrowMultiLineArgs = fn (
439+
$longVar1, $longerVar2,
440+
441+
& ... $muchLongerVar3) => $longVar1;

src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc.fixed

+21
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,24 @@ class ConstructorPropertyPromotionMultiLineAttributesIncorrectIndent
416416
// Do something.
417417
}
418418
}
419+
420+
$arrowNoArgs = fn () => $retrievedfromscope;
421+
422+
$arrowSingleLineArgs = fn (Type $param1, int $param2, string $param3): \ReturnType => $retrievedfromscope;
423+
424+
$arrowMultiLineArgs = fn (
425+
$longVar1,
426+
$longerVar2,
427+
&...$muchLongerVar3
428+
) => $longVar1;
429+
430+
$arrowNoArgs = fn ( )
431+
=> $retrievedfromscope;
432+
433+
$arrowSingleLineArgs = fn ( Type $param1 , int $param2, string $param3
434+
) : \ReturnType => $retrievedfromscope;
435+
436+
$arrowMultiLineArgs = fn (
437+
$longVar1, $longerVar2,
438+
& ... $muchLongerVar3
439+
) => $longVar1;

src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ public function getErrorList($testFile='FunctionDeclarationUnitTest.inc')
9999
371 => 1,
100100
402 => 1,
101101
406 => 1,
102+
432 => 1,
103+
435 => 1,
104+
436 => 2,
105+
440 => 1,
106+
441 => 2,
102107
];
103108
} else {
104109
$errors = [

0 commit comments

Comments
 (0)