diff --git a/src/Files/File.php b/src/Files/File.php index a5ae3df5f8..b0c717fa17 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -1781,6 +1781,8 @@ public function getMethodProperties(int $stackPtr) T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS, ]; + $hasColon = false; + for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) { if (($scopeOpener === null && $this->tokens[$i]['code'] === T_SEMICOLON) || ($scopeOpener !== null && $i === $scopeOpener) @@ -1800,11 +1802,17 @@ public function getMethodProperties(int $stackPtr) continue; } + if ($this->tokens[$i]['code'] === T_COLON) { + $hasColon = true; + continue; + } + if ($this->tokens[$i]['code'] === T_NULLABLE) { $nullableReturnType = true; + continue; } - if (isset($valid[$this->tokens[$i]['code']]) === true) { + if ($hasColon === true && isset($valid[$this->tokens[$i]['code']]) === true) { if ($returnTypeToken === false) { $returnTypeToken = $i; } diff --git a/tests/Core/Files/File/GetMethodPropertiesTest.inc b/tests/Core/Files/File/GetMethodPropertiesTest.inc index 7f572f66c5..ae9d5ef77b 100644 --- a/tests/Core/Files/File/GetMethodPropertiesTest.inc +++ b/tests/Core/Files/File/GetMethodPropertiesTest.inc @@ -221,6 +221,10 @@ $closure = function () use /*comment*/ ($a): Type {}; /* testClosureWithUseMultiParamWithReturnType */ $closure = function () use ($a, &$b, $c, $d, $e, $f, $g): ?array {}; +/* testMissingColonParseError */ +// Intentional parse error. +$closure = function () null { return null; }; + /* testArrowFunctionLiveCoding */ // Intentional parse error. This has to be the last test in the file. $fn = fn diff --git a/tests/Core/Files/File/GetMethodPropertiesTest.php b/tests/Core/Files/File/GetMethodPropertiesTest.php index 456e7dcf21..3de531e626 100644 --- a/tests/Core/Files/File/GetMethodPropertiesTest.php +++ b/tests/Core/Files/File/GetMethodPropertiesTest.php @@ -1450,6 +1450,31 @@ public function testClosureWithUseWithReturnType() } + /** + * Test handling of a parse error where the colon is missing from the return type declaration. + * + * @return void + */ + public function testMissingColonParseError() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected); + } + + /** * Test handling of closure declarations with a use variable import with a return type declaration. *