Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dd2717b

Browse files
Support for pipe operator in PossiblyPure*Collector
1 parent ea53cad commit dd2717b

9 files changed

+148
-14
lines changed

‎src/Rules/DeadCode/PossiblyPureFuncCallCollector.php‎

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,33 @@ public function getNodeType(): string
2727

2828
public function processNode(Node $node, Scope $scope)
2929
{
30-
if (!$node->expr instanceof Node\Expr\FuncCall || $node->expr->isFirstClassCallable()) {
30+
$expr = $node->expr;
31+
if ($expr instanceof Node\Expr\BinaryOp\Pipe) {
32+
if ($expr->right instanceof Node\Expr\FuncCall) {
33+
if (!$expr->right->isFirstClassCallable()) {
34+
return null;
35+
}
36+
37+
$expr = new Node\Expr\FuncCall($expr->right->name, []);
38+
} elseif ($expr->right instanceof Node\Expr\ArrowFunction) {
39+
$expr = $expr->right->expr;
40+
}
41+
}
42+
if (!$expr instanceof Node\Expr\FuncCall) {
43+
return null;
44+
}
45+
if ($expr->isFirstClassCallable()) {
3146
return null;
3247
}
33-
if (!$node->expr->name instanceof Node\Name) {
48+
if (!$expr->name instanceof Node\Name) {
3449
return null;
3550
}
3651

37-
if (!$this->reflectionProvider->hasFunction($node->expr->name, $scope)) {
52+
if (!$this->reflectionProvider->hasFunction($expr->name, $scope)) {
3853
return null;
3954
}
4055

41-
$functionReflection = $this->reflectionProvider->getFunction($node->expr->name, $scope);
56+
$functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope);
4257
if (!$functionReflection->isPure()->maybe()) {
4358
return null;
4459
}

‎src/Rules/DeadCode/PossiblyPureMethodCallCollector.php‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,31 @@ public function getNodeType(): string
2626

2727
public function processNode(Node $node, Scope $scope)
2828
{
29-
if (!$node->expr instanceof Node\Expr\MethodCall && !$node->expr instanceof Node\Expr\NullsafeMethodCall) {
29+
$expr = $node->expr;
30+
if ($expr instanceof Node\Expr\BinaryOp\Pipe) {
31+
if ($expr->right instanceof Node\Expr\MethodCall || $expr->right instanceof Node\Expr\NullsafeMethodCall) {
32+
if (!$expr->right->isFirstClassCallable()) {
33+
return null;
34+
}
35+
36+
$expr = new Node\Expr\MethodCall($expr->right->var, $expr->right->name, []);
37+
} elseif ($expr->right instanceof Node\Expr\ArrowFunction) {
38+
$expr = $expr->right->expr;
39+
}
40+
}
41+
42+
if (!$expr instanceof Node\Expr\MethodCall && !$expr instanceof Node\Expr\NullsafeMethodCall) {
3043
return null;
3144
}
32-
if ($node->expr->isFirstClassCallable()) {
45+
if ($expr->isFirstClassCallable()) {
3346
return null;
3447
}
35-
if (!$node->expr->name instanceof Node\Identifier) {
48+
if (!$expr->name instanceof Node\Identifier) {
3649
return null;
3750
}
3851

39-
$methodName = $node->expr->name->toString();
40-
$calledOnType = $scope->getType($node->expr->var);
52+
$methodName = $expr->name->toString();
53+
$calledOnType = $scope->getType($expr->var);
4154
if (!$calledOnType->hasMethod($methodName)->yes()) {
4255
return null;
4356
}

‎src/Rules/DeadCode/PossiblyPureStaticCallCollector.php‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,31 @@ public function getNodeType(): string
2626

2727
public function processNode(Node $node, Scope $scope)
2828
{
29-
if (!$node->expr instanceof Node\Expr\StaticCall || $node->expr->isFirstClassCallable()) {
29+
$expr = $node->expr;
30+
if ($expr instanceof Node\Expr\BinaryOp\Pipe) {
31+
if ($expr->right instanceof Node\Expr\StaticCall) {
32+
if (!$expr->right->isFirstClassCallable()) {
33+
return null;
34+
}
35+
36+
$expr = new Node\Expr\StaticCall($expr->right->class, $expr->right->name, []);
37+
} elseif ($expr->right instanceof Node\Expr\ArrowFunction) {
38+
$expr = $expr->right->expr;
39+
}
40+
}
41+
if (!$expr instanceof Node\Expr\StaticCall || $expr->isFirstClassCallable()) {
3042
return null;
3143
}
32-
if (!$node->expr->name instanceof Node\Identifier) {
44+
if (!$expr->name instanceof Node\Identifier) {
3345
return null;
3446
}
3547

36-
if (!$node->expr->class instanceof Node\Name) {
48+
if (!$expr->class instanceof Node\Name) {
3749
return null;
3850
}
3951

40-
$methodName = $node->expr->name->toString();
41-
$calledOnType = $scope->resolveTypeByName($node->expr->class);
52+
$methodName = $expr->name->toString();
53+
$calledOnType = $scope->resolveTypeByName($expr->class);
4254
$methodReflection = $scope->getMethodReflection($calledOnType, $methodName);
4355

4456
if ($methodReflection === null) {

‎tests/PHPStan/Rules/DeadCode/CallToFunctionStatementWithoutImpurePointsRuleTest.php‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\Rules\Rule;
66
use PHPStan\Testing\RuleTestCase;
7+
use PHPUnit\Framework\Attributes\RequiresPhp;
78

89
/**
910
* @extends RuleTestCase<CallToFunctionStatementWithoutImpurePointsRule>
@@ -26,6 +27,21 @@ public function testRule(): void
2627
]);
2728
}
2829

30+
#[RequiresPhp('>= 8.5')]
31+
public function testPipeOperator(): void
32+
{
33+
$this->analyse([__DIR__ . '/data/call-to-function-without-impure-points-pipe.php'], [
34+
[
35+
'Call to function CallToFunctionWithoutImpurePointsPipe\myFunc() on a separate line has no effect.',
36+
9,
37+
],
38+
[
39+
'Call to function CallToFunctionWithoutImpurePointsPipe\myFunc() on a separate line has no effect.',
40+
10,
41+
],
42+
]);
43+
}
44+
2945
protected function getCollectors(): array
3046
{
3147
return [

‎tests/PHPStan/Rules/DeadCode/CallToMethodStatementWithoutImpurePointsRuleTest.php‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ public function testBug12379(): void
9292
$this->analyse([__DIR__ . '/data/bug-12379.php'], []);
9393
}
9494

95+
#[RequiresPhp('>= 8.5')]
96+
public function testPipeOperator(): void
97+
{
98+
$this->analyse([__DIR__ . '/data/call-to-method-without-impure-points-pipe.php'], [
99+
[
100+
'Call to method CallToMethodWithoutImpurePointsPipe\Foo::maybePure() on a separate line has no effect.',
101+
17,
102+
],
103+
[
104+
'Call to method CallToMethodWithoutImpurePointsPipe\Foo::maybePure() on a separate line has no effect.',
105+
18,
106+
],
107+
]);
108+
}
109+
95110
protected function getCollectors(): array
96111
{
97112
return [

‎tests/PHPStan/Rules/DeadCode/CallToStaticMethodStatementWithoutImpurePointsRuleTest.php‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\Rules\Rule;
66
use PHPStan\Testing\RuleTestCase;
7+
use PHPUnit\Framework\Attributes\RequiresPhp;
78

89
/**
910
* @extends RuleTestCase<CallToStaticMethodStatementWithoutImpurePointsRule>
@@ -58,6 +59,21 @@ public function testRule(): void
5859
]);
5960
}
6061

62+
#[RequiresPhp('>= 8.5')]
63+
public function testPipeOperator(): void
64+
{
65+
$this->analyse([__DIR__ . '/data/call-to-static-method-without-impure-points-pipe.php'], [
66+
[
67+
'Call to CallToStaticMethodWithoutImpurePointsPipe\Foo::doFoo() on a separate line has no effect.',
68+
16,
69+
],
70+
[
71+
'Call to CallToStaticMethodWithoutImpurePointsPipe\Foo::doFoo() on a separate line has no effect.',
72+
17,
73+
],
74+
]);
75+
}
76+
6177
protected function getCollectors(): array
6278
{
6379
return [
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php // lint >= 8.5
2+
3+
namespace CallToFunctionWithoutImpurePointsPipe;
4+
5+
function myFunc()
6+
{
7+
}
8+
9+
5 |> myFunc(...);
10+
5 |> fn ($x) => myFunc($x);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php // lint >= 8.5
2+
3+
namespace CallToMethodWithoutImpurePointsPipe;
4+
5+
class Foo
6+
{
7+
8+
public function maybePure(int $o): int
9+
{
10+
return 5;
11+
}
12+
13+
}
14+
15+
function (): void {
16+
$foo = new Foo();
17+
5 |> $foo->maybePure(...);
18+
5 |> fn ($x) => $foo->maybePure($x);
19+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace CallToStaticMethodWithoutImpurePointsPipe;
4+
5+
class Foo
6+
{
7+
8+
public static function doFoo(int $o): int
9+
{
10+
return 1;
11+
}
12+
13+
}
14+
15+
function (): void {
16+
5 |> Foo::doFoo(...);
17+
5 |> fn ($x) => Foo::doFoo($x);
18+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /