Skip to content

Commit 38daf37

Browse files
committed
Arrow function - check nullsafe returned by ref
1 parent 6c3bf6b commit 38daf37

File tree

5 files changed

+96
-0
lines changed

5 files changed

+96
-0
lines changed

build.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@
133133
<arg path="tests/PHPStan/Rules/Properties/data/default-value-for-promoted-property.php"/>
134134
<arg value="--exclude"/>
135135
<arg path="tests/PHPStan/Rules/Operators/data/invalid-assign-var.php"/>
136+
<arg value="--exclude"/>
137+
<arg path="tests/PHPStan/Rules/Functions/data/arrow-function-nullsafe-by-ref.php"/>
136138
<arg path="src" />
137139
<arg path="tests" />
138140
<arg path="compiler/src" />

conf/config.level0.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ rules:
3030
- PHPStan\Rules\Classes\InvalidPromotedPropertiesRule
3131
- PHPStan\Rules\Classes\NewStaticRule
3232
- PHPStan\Rules\Exceptions\ThrowExpressionRule
33+
- PHPStan\Rules\Functions\ArrowFunctionReturnNullsafeByRefRule
3334
- PHPStan\Rules\Functions\CallToFunctionParametersRule
3435
- PHPStan\Rules\Functions\ExistingClassesInArrowFunctionTypehintsRule
3536
- PHPStan\Rules\Functions\ExistingClassesInClosureTypehintsRule
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\NullsafeCheck;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Rules\RuleErrorBuilder;
10+
11+
/**
12+
* @implements Rule<Node\Expr\ArrowFunction>
13+
*/
14+
class ArrowFunctionReturnNullsafeByRefRule implements Rule
15+
{
16+
17+
private NullsafeCheck $nullsafeCheck;
18+
19+
public function __construct(NullsafeCheck $nullsafeCheck)
20+
{
21+
$this->nullsafeCheck = $nullsafeCheck;
22+
}
23+
24+
public function getNodeType(): string
25+
{
26+
return Node\Expr\ArrowFunction::class;
27+
}
28+
29+
public function processNode(Node $node, Scope $scope): array
30+
{
31+
if (!$node->byRef) {
32+
return [];
33+
}
34+
35+
if (!$this->nullsafeCheck->containsNullSafe($node->expr)) {
36+
return [];
37+
}
38+
39+
return [
40+
RuleErrorBuilder::message('Nullsafe cannot be returned by reference.')->nonIgnorable()->build(),
41+
];
42+
}
43+
44+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PHPStan\Rules\NullsafeCheck;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Testing\RuleTestCase;
8+
9+
/**
10+
* @extends RuleTestCase<ArrowFunctionReturnNullsafeByRefRule>
11+
*/
12+
class ArrowFunctionReturnNullsafeByRefRuleTest extends RuleTestCase
13+
{
14+
15+
protected function getRule(): Rule
16+
{
17+
return new ArrowFunctionReturnNullsafeByRefRule(new NullsafeCheck());
18+
}
19+
20+
public function testRule(): void
21+
{
22+
if (!self::$useStaticReflectionProvider) {
23+
$this->markTestSkipped('Test requires static reflection.');
24+
}
25+
26+
$this->analyse([__DIR__ . '/data/arrow-function-nullsafe-by-ref.php'], [
27+
[
28+
'Nullsafe cannot be returned by reference.',
29+
6,
30+
],
31+
]);
32+
}
33+
34+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace ArrowFunctionNullsafeReturnByRef;
4+
5+
function (\stdClass $foo): void {
6+
fn &() => $foo?->bar;
7+
};
8+
9+
function (\stdClass $foo): void {
10+
fn &() => $foo->bar;
11+
};
12+
13+
function (\stdClass $foo): void {
14+
fn () => $foo?->bar;
15+
};

0 commit comments

Comments
 (0)