Skip to content

Commit df4a812

Browse files
committed
Tokenizer/PHP: bug fix for missing parenthesis owner for method named "fn"
When a function is named "fn", the `function` keyword should be set as the parenthesis owner. While this works on PHPCS 3.x, I found while making PHPCSUtils compatible with 4.x, that this was broken on PHPCS 4.x for PHP 7.2 and 7.3 since commit da0d224. This was due to token being seen as a `T_FN` token after the initial tokenization fixing round, so the `Tokenizer::createTokenMap()` would receive the `T_FN` token and not set the parenthesis owner index. The additional token processing run after that, would realize this is not in actual fact an arrow function and undo the retokenization (from `T_FN` back to `T_STRING`), which leaves the parentheses for this function declaration without an owner. Fixed now by preventing the initial `T_STRING` to `T_FN` retokenization if the keyword is used in a context where the token should always be a `T_STRING`.
1 parent 0e71305 commit df4a812

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

src/Tokenizers/PHP.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,8 @@ protected function tokenize($string)
22172217
if ($tokenIsArray === true
22182218
&& $token[0] === T_STRING
22192219
&& strtolower($token[1]) === 'fn'
2220+
&& isset(static::T_STRING_CONTEXTS[$finalTokens[$lastNotEmptyToken]['code']]) === false
2221+
&& $finalTokens[$lastNotEmptyToken]['content'] !== '&'
22202222
) {
22212223
// Modify the original token stack so that
22222224
// future checks (like looking for T_NULLABLE) can

tests/Core/Tokenizers/Tokenizer/CreateTokenMapParenthesesTest.inc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,14 @@ function name($a, $b/* testFunctionParenthesesCloser */) {}
6060
function &returnByRef ($a, $b/* testFunctionParenthesesCloserReturnByRef */) {}
6161

6262
class ReservedKeyword {
63-
/* testFunctionParenthesesOwnerKeywordName */
64-
public function match($a, $b/* testFunctionParenthesesCloserKeywordName */) {}
63+
/* testFunctionParenthesesOwnerKeywordNameMatch */
64+
public function match($a, $b/* testFunctionParenthesesCloserKeywordNameMatch */) {}
65+
66+
/* testFunctionParenthesesOwnerKeywordNameFn */
67+
public function fn($a, $b/* testFunctionParenthesesCloserKeywordNameFn */) {}
68+
69+
/* testFunctionParenthesesOwnerKeywordNameFnReturnByRef */
70+
public function &fn($a, $b/* testFunctionParenthesesCloserKeywordNameFnReturnByRef */) {}
6571
}
6672

6773
/* testClosureParenthesesOwner */

tests/Core/Tokenizers/Tokenizer/CreateTokenMapParenthesesTest.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,16 @@ public static function dataParenthesesWithOwner()
139139
'testMarker' => '/* testFunctionParenthesesOwnerReturnByRef */',
140140
'tokenCode' => T_FUNCTION,
141141
],
142-
'function declaration, keyword as function name' => [
143-
'testMarker' => '/* testFunctionParenthesesOwnerKeywordName */',
142+
'function declaration, "match" as function name' => [
143+
'testMarker' => '/* testFunctionParenthesesOwnerKeywordNameMatch */',
144+
'tokenCode' => T_FUNCTION,
145+
],
146+
'function declaration, "fn" as function name' => [
147+
'testMarker' => '/* testFunctionParenthesesOwnerKeywordNameFn */',
148+
'tokenCode' => T_FUNCTION,
149+
],
150+
'function declaration, "&fn" as function name' => [
151+
'testMarker' => '/* testFunctionParenthesesOwnerKeywordNameFnReturnByRef */',
144152
'tokenCode' => T_FUNCTION,
145153
],
146154
'closure declaration' => [
@@ -276,7 +284,7 @@ public static function dataParenthesesWithoutOwner()
276284

277285

278286
/**
279-
* Test parentheses owner tokens when used without parentheses (where possible) do *not* the "parenthesis_*" token indexes set.
287+
* Test parentheses owner tokens when used without parentheses (where possible) do *not* have the "parenthesis_*" token indexes set.
280288
*
281289
* @param string $testMarker The comment prefacing the target token.
282290
* @param int|string $tokenCode The token code to look for.

0 commit comments

Comments
 (0)