Skip to content

Commit 7f4fd39

Browse files
authored
Merge pull request #1354 from fredden/feature/fixer-conflict/PSR12.Functions.ReturnTypeDeclaration
Avoid PHP error on parse error in `PSR12.Functions.ReturnTypeDeclaration`
2 parents 44c338e + 124b61f commit 7f4fd39

File tree

7 files changed

+67
-28
lines changed

7 files changed

+67
-28
lines changed

src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,35 @@ public function process(File $phpcsFile, int $stackPtr)
6161
$returnType = $phpcsFile->findPrevious(T_NULLABLE, ($returnType - 1));
6262
}
6363

64+
$colon = $phpcsFile->findPrevious(T_COLON, ($returnType - 1), $tokens[$stackPtr]['parenthesis_closer']);
65+
if ($colon === false) {
66+
// Parse error / live coding.
67+
return;
68+
}
69+
6470
if ($tokens[($returnType - 1)]['code'] !== T_WHITESPACE
6571
|| $tokens[($returnType - 1)]['content'] !== ' '
66-
|| $tokens[($returnType - 2)]['code'] !== T_COLON
72+
|| ($returnType - 2) !== $colon
6773
) {
6874
$error = 'There must be a single space between the colon and type in a return type declaration';
69-
if ($tokens[($returnType - 1)]['code'] === T_WHITESPACE
70-
&& $tokens[($returnType - 2)]['code'] === T_COLON
71-
) {
72-
$fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType');
73-
if ($fix === true) {
74-
$phpcsFile->fixer->replaceToken(($returnType - 1), ' ');
75-
}
76-
} elseif ($tokens[($returnType - 1)]['code'] === T_COLON) {
75+
76+
$nonWhitespaceToken = $phpcsFile->findNext(T_WHITESPACE, ($colon + 1), $returnType, true);
77+
if ($nonWhitespaceToken !== false) {
78+
$phpcsFile->addError($error, $returnType, 'SpaceBeforeReturnType');
79+
} else {
7780
$fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType');
7881
if ($fix === true) {
82+
$phpcsFile->fixer->beginChangeset();
83+
for ($i = ($returnType - 1); $i > $colon; $i--) {
84+
$phpcsFile->fixer->replaceToken($i, '');
85+
}
86+
7987
$phpcsFile->fixer->addContentBefore($returnType, ' ');
88+
$phpcsFile->fixer->endChangeset();
8089
}
81-
} else {
82-
$phpcsFile->addError($error, $returnType, 'SpaceBeforeReturnType');
8390
}
8491
}
8592

86-
$colon = $phpcsFile->findPrevious(T_COLON, $returnType);
8793
if ($tokens[($colon - 1)]['code'] !== T_CLOSE_PARENTHESIS) {
8894
$error = 'There must not be a space before the colon in a return type declaration';
8995
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($colon - 1), null, true);

src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc renamed to src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ function functionName(?string $arg1, ?int &$arg2):
6464
fn (?\DateTime $arg) : ?\DateTime => $arg;
6565

6666
return (!$a ? [ new class { public function b(): c {} } ] : []);
67+
68+
// This should be fixed in one fixer loop iteration.
69+
function multipleWhitespaceTokens():
70+
71+
72+
73+
74+
?int {}

src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed renamed to src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.1.inc.fixed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,6 @@ function functionName(?string $arg1, ?int &$arg2): ?string {}
6060
fn (?\DateTime $arg): ?\DateTime => $arg;
6161

6262
return (!$a ? [ new class { public function b(): c {} } ] : []);
63+
64+
// This should be fixed in one fixer loop iteration.
65+
function multipleWhitespaceTokens(): ?int {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
// Intentional parse error. There should be a colon between the function parameters and its return type.
4+
$closure = function () null { return null; };
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
// Intentional parse error. There should be a colon between the function 'use' and its return type.
4+
$closure = function ($foo) use ($bar) string { return 'baz'; };
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
// Intentional parse error. There should be a colon between the function parameters and its return type.
4+
function foo($obj = new DateTime(datetime: "now")) null {}

src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,32 @@ final class ReturnTypeDeclarationUnitTest extends AbstractSniffTestCase
2727
* The key of the array should represent the line number and the value
2828
* should represent the number of errors that should occur on that line.
2929
*
30+
* @param string $testFile The name of the file being tested.
31+
*
3032
* @return array<int, int>
3133
*/
32-
protected function getErrorList()
34+
protected function getErrorList($testFile = '')
3335
{
34-
return [
35-
27 => 1,
36-
28 => 1,
37-
35 => 2,
38-
41 => 2,
39-
48 => 2,
40-
52 => 1,
41-
55 => 1,
42-
56 => 1,
43-
59 => 1,
44-
60 => 1,
45-
62 => 1,
46-
64 => 1,
47-
];
36+
switch ($testFile) {
37+
case 'ReturnTypeDeclarationUnitTest.1.inc':
38+
return [
39+
27 => 1,
40+
28 => 1,
41+
35 => 2,
42+
41 => 2,
43+
48 => 2,
44+
52 => 1,
45+
55 => 1,
46+
56 => 1,
47+
59 => 1,
48+
60 => 1,
49+
62 => 1,
50+
64 => 1,
51+
74 => 1,
52+
];
53+
default:
54+
return [];
55+
}
4856
}
4957

5058

@@ -54,9 +62,11 @@ protected function getErrorList()
5462
* The key of the array should represent the line number and the value
5563
* should represent the number of warnings that should occur on that line.
5664
*
65+
* @param string $testFile The name of the file being tested.
66+
*
5767
* @return array<int, int>
5868
*/
59-
protected function getWarningList()
69+
protected function getWarningList($testFile = '')
6070
{
6171
return [];
6272
}

0 commit comments

Comments
 (0)