Skip to content

Commit d4d3271

Browse files
committed
Handle parse error in File::getMethodProperties()
While investigating the cause of a PHP Fatal error while processing some input in the `PSR12.Functions.ReturnTypeDeclaration` sniff, I noticed that the `File::getMethodProperties()` method did not return sensible values in for some parse errors. The input file in question was `src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.2.inc`, which contains an intentional parse error. The `File::getMethodProperties()` method claimed that the return type of the `test` function was `<< HEAD`, which is nonsense. The change in this commit safeguards from such parse errors and resolves the issue that was being encountered downstream in the sniff.
1 parent e1fcbea commit d4d3271

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/Files/File.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,8 @@ public function getMethodProperties(int $stackPtr)
17811781
T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS,
17821782
];
17831783

1784+
$hasColon = false;
1785+
17841786
for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) {
17851787
if (($scopeOpener === null && $this->tokens[$i]['code'] === T_SEMICOLON)
17861788
|| ($scopeOpener !== null && $i === $scopeOpener)
@@ -1800,11 +1802,17 @@ public function getMethodProperties(int $stackPtr)
18001802
continue;
18011803
}
18021804

1805+
if ($this->tokens[$i]['code'] === T_COLON) {
1806+
$hasColon = true;
1807+
continue;
1808+
}
1809+
18031810
if ($this->tokens[$i]['code'] === T_NULLABLE) {
18041811
$nullableReturnType = true;
1812+
continue;
18051813
}
18061814

1807-
if (isset($valid[$this->tokens[$i]['code']]) === true) {
1815+
if ($hasColon === true && isset($valid[$this->tokens[$i]['code']]) === true) {
18081816
if ($returnTypeToken === false) {
18091817
$returnTypeToken = $i;
18101818
}

tests/Core/Files/File/GetMethodPropertiesTest.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ $closure = function () use /*comment*/ ($a): Type {};
221221
/* testClosureWithUseMultiParamWithReturnType */
222222
$closure = function () use ($a, &$b, $c, $d, $e, $f, $g): ?array {};
223223

224+
/* testMissingColonParseError */
225+
// Intentional parse error.
226+
$closure = function () null { return null; };
227+
224228
/* testArrowFunctionLiveCoding */
225229
// Intentional parse error. This has to be the last test in the file.
226230
$fn = fn

tests/Core/Files/File/GetMethodPropertiesTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,31 @@ public function testClosureWithUseWithReturnType()
14501450
}
14511451

14521452

1453+
/**
1454+
* Test handling of a parse error where the colon is missing from the return type declaration.
1455+
*
1456+
* @return void
1457+
*/
1458+
public function testMissingColonParseError()
1459+
{
1460+
// Offsets are relative to the T_CLOSURE token.
1461+
$expected = [
1462+
'scope' => 'public',
1463+
'scope_specified' => false,
1464+
'return_type' => '',
1465+
'return_type_token' => false,
1466+
'return_type_end_token' => false,
1467+
'nullable_return_type' => false,
1468+
'is_abstract' => false,
1469+
'is_final' => false,
1470+
'is_static' => false,
1471+
'has_body' => true,
1472+
];
1473+
1474+
$this->getMethodPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
1475+
}
1476+
1477+
14531478
/**
14541479
* Test handling of closure declarations with a use variable import with a return type declaration.
14551480
*

0 commit comments

Comments
 (0)