Skip to content

Commit 70a75f6

Browse files
committed
Use statement result of analysed anonymous class to inform about throw points and impure points
1 parent 00bad36 commit 70a75f6

File tree

8 files changed

+84
-12
lines changed

8 files changed

+84
-12
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,8 +749,15 @@ private function processStmtNode(
749749
} elseif ($stmt instanceof Node\Stmt\Expression) {
750750
$earlyTerminationExpr = $this->findEarlyTerminatingExpr($stmt->expr, $scope);
751751
$hasAssign = false;
752-
$result = $this->processExprNode($stmt, $stmt->expr, $scope, static function (Node $node, Scope $scope) use ($nodeCallback, &$hasAssign): void {
752+
$currentScope = $scope;
753+
$result = $this->processExprNode($stmt, $stmt->expr, $scope, static function (Node $node, Scope $scope) use ($nodeCallback, $currentScope, &$hasAssign): void {
753754
$nodeCallback($node, $scope);
755+
if ($scope->getAnonymousFunctionReflection() !== $currentScope->getAnonymousFunctionReflection()) {
756+
return;
757+
}
758+
if ($scope->getFunction() !== $currentScope->getFunction()) {
759+
return;
760+
}
754761
if (!$node instanceof VariableAssignNode && !$node instanceof PropertyAssignNode) {
755762
return;
756763
}
@@ -3152,7 +3159,31 @@ static function (): void {
31523159

31533160
} else {
31543161
$classReflection = $this->reflectionProvider->getAnonymousClassReflection($expr->class, $scope); // populates $expr->class->name
3155-
$this->processStmtNode($expr->class, $scope, $nodeCallback, StatementContext::createTopLevel());
3162+
$constructorResult = null;
3163+
$this->processStmtNode($expr->class, $scope, static function (Node $node, Scope $scope) use ($nodeCallback, $classReflection, &$constructorResult): void {
3164+
$nodeCallback($node, $scope);
3165+
if (!$node instanceof MethodReturnStatementsNode) {
3166+
return;
3167+
}
3168+
if ($constructorResult !== null) {
3169+
return;
3170+
}
3171+
$currentClassReflection = $node->getClassReflection();
3172+
if ($currentClassReflection->getName() !== $classReflection->getName()) {
3173+
return;
3174+
}
3175+
if (!$currentClassReflection->hasConstructor()) {
3176+
return;
3177+
}
3178+
if ($currentClassReflection->getConstructor()->getName() !== $node->getMethodReflection()->getName()) {
3179+
return;
3180+
}
3181+
$constructorResult = $node;
3182+
}, StatementContext::createTopLevel());
3183+
if ($constructorResult !== null) {
3184+
$throwPoints = array_merge($throwPoints, $constructorResult->getStatementResult()->getThrowPoints());
3185+
$impurePoints = array_merge($impurePoints, $constructorResult->getImpurePoints());
3186+
}
31563187
if ($classReflection->hasConstructor()) {
31573188
$constructorReflection = $classReflection->getConstructor();
31583189
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs(

src/Rules/DeadCode/BetterNoopRule.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,14 @@ public function processNode(Node $node, Scope $scope): array
9393
}
9494
}
9595

96+
if ($expr instanceof Node\Expr\New_ && $expr->class instanceof Node\Name) {
97+
// handled by CallToConstructorStatementWithoutSideEffectsRule
98+
return [];
99+
}
100+
96101
if (
97102
$expr instanceof Node\Expr\NullsafeMethodCall
98103
|| $expr instanceof Node\Expr\MethodCall
99-
|| $expr instanceof Node\Expr\New_
100104
|| $expr instanceof Node\Expr\StaticCall
101105
) {
102106
// handled by *WithoutSideEffectsRule rules

tests/PHPStan/Analyser/data/AnonymousClassesWithComments.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
// Test comment
4-
new class () {
4+
$a = new class () {
55

66
public function doFoo(): void
77
{
@@ -10,8 +10,7 @@ public function doFoo(): void
1010

1111
};
1212

13-
/* Test comment */
14-
new class () {
13+
$a = /* Test comment */ new class () {
1514

1615
public function doFoo(): void
1716
{
@@ -20,8 +19,7 @@ public function doFoo(): void
2019

2120
};
2221

23-
/** Test comment */
24-
new class () {
22+
$a = /** Test comment */ new class () {
2523

2624
public function doFoo(): void
2725
{

tests/PHPStan/Analyser/data/anonymous-class-with-inherited-constructor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public function __construct(int $i, int $j)
1414
}
1515

1616
function () {
17-
new class (1, 2) extends Foo
17+
$a = new class (1, 2) extends Foo
1818
{
1919

2020
};
@@ -30,7 +30,7 @@ final public function __construct(int $i, int $j)
3030
}
3131

3232
function () {
33-
new class (1, 2) extends Bar
33+
$a = new class (1, 2) extends Bar
3434
{
3535

3636
};

tests/PHPStan/Analyser/data/bug-6442.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class B extends A
1717
use T;
1818
}
1919

20-
new class() extends B
20+
$a = new class() extends B
2121
{
2222
use T;
2323
};

tests/PHPStan/Analyser/traits/AnonymousClassUsingTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AnonymousTraitClass;
44

5-
new class implements FooInterface {
5+
$a = new class implements FooInterface {
66

77
use TraitWithTypeSpecification;
88

tests/PHPStan/Rules/DeadCode/BetterNoopRuleTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ public function testRuleImpurePoints(): void
132132
'Expression "$b()" on a separate line does not do anything.',
133133
59,
134134
],
135+
[
136+
'Expression "new class…" on a separate line does not do anything.',
137+
98,
138+
],
139+
[
140+
'Expression "new class…" on a separate line does not do anything.',
141+
104,
142+
],
135143
]);
136144
}
137145

tests/PHPStan/Rules/DeadCode/data/noop-impure-points.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,35 @@ public function doFunctionWithByRef(bool $b, array $a): void
8383
$func($a, 1);
8484
}
8585

86+
public function anonymousClassWithSideEffect(): void
87+
{
88+
new class () {
89+
public function __construct()
90+
{
91+
echo '1';
92+
}
93+
};
94+
}
95+
96+
public function anonymousClassWithoutConstructor(): void
97+
{
98+
new class () {
99+
};
100+
}
101+
102+
public function anonymousClassWithPureConstructor(): void
103+
{
104+
new class () {
105+
106+
/** @var int */
107+
private $i;
108+
109+
public function __construct()
110+
{
111+
$this->i = 1;
112+
}
113+
114+
};
115+
}
116+
86117
}

0 commit comments

Comments
 (0)