Skip to content

Commit 4a1be9a

Browse files
kubawerloskeradus
authored andcommitted
StaticLambdaFixer - fix for arrow function used in class with $this
1 parent eae6b9b commit 4a1be9a

File tree

2 files changed

+77
-9
lines changed

2 files changed

+77
-9
lines changed

src/Fixer/FunctionNotation/StaticLambdaFixer.php

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ public function isRisky()
6464
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
6565
{
6666
$analyzer = new TokensAnalyzer($tokens);
67-
6867
$expectedFunctionKinds = [T_FUNCTION];
68+
6969
if (\PHP_VERSION_ID >= 70400) {
7070
$expectedFunctionKinds[] = T_FN;
7171
}
@@ -76,21 +76,22 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
7676
}
7777

7878
$prev = $tokens->getPrevMeaningfulToken($index);
79+
7980
if ($tokens[$prev]->isGivenKind(T_STATIC)) {
8081
continue; // lambda is already 'static'
8182
}
8283

8384
$argumentsStartIndex = $tokens->getNextTokenOfKind($index, ['(']);
8485
$argumentsEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStartIndex);
8586

86-
// figure out where the lambda starts ...
87-
$lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, ['{', [T_DOUBLE_ARROW]]);
87+
// figure out where the lambda starts and ends
8888

89-
// ... and where it ends
90-
if ($tokens[$lambdaOpenIndex]->isGivenKind(T_DOUBLE_ARROW)) {
91-
$lambdaEndIndex = $tokens->getNextTokenOfKind($lambdaOpenIndex, [';']);
92-
} else {
89+
if ($tokens[$index]->isGivenKind(T_FUNCTION)) {
90+
$lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, ['{']);
9391
$lambdaEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $lambdaOpenIndex);
92+
} else { // T_FN
93+
$lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, [[T_DOUBLE_ARROW]]);
94+
$lambdaEndIndex = $this->findExpressionEnd($tokens, $lambdaOpenIndex);
9495
}
9596

9697
if ($this->hasPossibleReferenceToThis($tokens, $lambdaOpenIndex, $lambdaEndIndex)) {
@@ -110,6 +111,37 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
110111
}
111112
}
112113

114+
/**
115+
* @param int $index
116+
*
117+
* @return int
118+
*/
119+
private function findExpressionEnd(Tokens $tokens, $index)
120+
{
121+
$nextIndex = $tokens->getNextMeaningfulToken($index);
122+
123+
while (null !== $nextIndex) {
124+
/** @var Token $nextToken */
125+
$nextToken = $tokens[$nextIndex];
126+
127+
if ($nextToken->equalsAny([',', ';', [T_CLOSE_TAG]])) {
128+
break;
129+
}
130+
131+
/** @var null|array{isStart: bool, type: int} $blockType */
132+
$blockType = Tokens::detectBlockType($nextToken);
133+
134+
if (null !== $blockType && $blockType['isStart']) {
135+
$nextIndex = $tokens->findBlockEnd($blockType['type'], $nextIndex);
136+
}
137+
138+
$index = $nextIndex;
139+
$nextIndex = $tokens->getNextMeaningfulToken($index);
140+
}
141+
142+
return $index;
143+
}
144+
113145
/**
114146
* Returns 'true' if there is a possible reference to '$this' within the given tokens index range.
115147
*
@@ -138,6 +170,7 @@ private function hasPossibleReferenceToThis(Tokens $tokens, $startIndex, $endInd
138170

139171
if ($tokens[$i]->equals('$')) {
140172
$nextIndex = $tokens->getNextMeaningfulToken($i);
173+
141174
if ($tokens[$nextIndex]->isGivenKind(T_VARIABLE)) {
142175
return true; // "$$a" case
143176
}

tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,12 @@ public function provideFixPhp74Cases()
258258
'<?php $a /**/ = /**/ fn() => null;',
259259
],
260260
[
261-
'<?php $a /**/ = /**/static fn() => null;',
262-
'<?php $a /**/ = /**/fn() => null;',
261+
'<?php $a /**/ = /**/static fn() => null; echo $this->foo();',
262+
'<?php $a /**/ = /**/fn() => null; echo $this->foo();',
263+
],
264+
[
265+
'<?php $a /**/ = /**/ static fn() => null ?> <?php echo $this->foo();',
266+
'<?php $a /**/ = /**/ fn() => null ?> <?php echo $this->foo();',
263267
],
264268
[
265269
'<?php
@@ -277,6 +281,37 @@ public function C()
277281
'<?php static fn($a = ["foo" => "bar"]) => [];',
278282
'<?php fn($a = ["foo" => "bar"]) => [];',
279283
],
284+
[
285+
'<?php class Foo {
286+
public function getNames()
287+
{
288+
return \array_map(
289+
static fn ($item) => $item->getName(),
290+
$this->getItems()
291+
);
292+
}
293+
}',
294+
'<?php class Foo {
295+
public function getNames()
296+
{
297+
return \array_map(
298+
fn ($item) => $item->getName(),
299+
$this->getItems()
300+
);
301+
}
302+
}',
303+
],
304+
[
305+
'<?php class Foo {
306+
public function getNames()
307+
{
308+
return \array_map(
309+
fn ($item) => $item->getName(1, $this->foo()),
310+
$this->getItems()
311+
);
312+
}
313+
}',
314+
],
280315
];
281316
}
282317
}

0 commit comments

Comments
 (0)