Skip to content

Commit 94afa40

Browse files
VincentLangletphpstan-bot
authored andcommitted
Avoid duplicated InternalThrowPoint when simulating ArrayAccess calls (phpstan#5222)
1 parent 6f4462f commit 94afa40

6 files changed

Lines changed: 73 additions & 4 deletions

File tree

src/Analyser/ExprHandler/ArrayDimFetchHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\Analyser\NodeScopeResolver;
1919
use PHPStan\Analyser\NoopNodeCallback;
2020
use PHPStan\DependencyInjection\AutowiredService;
21+
use PHPStan\Node\Expr\TypeExpr;
2122
use PHPStan\Type\NeverType;
2223
use PHPStan\Type\ObjectType;
2324
use PHPStan\Type\Type;
@@ -96,7 +97,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
9697
if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) {
9798
$throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode(
9899
$stmt,
99-
new MethodCall($expr->var, 'offsetGet'),
100+
new MethodCall(new TypeExpr($varType), 'offsetGet'),
100101
$scope,
101102
$storage,
102103
new NoopNodeCallback(),

src/Analyser/ExprHandler/AssignHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ public function processAssignVar(
478478
) {
479479
$throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode(
480480
$stmt,
481-
new MethodCall($originalVar->var, 'offsetSet'),
481+
new MethodCall(new TypeExpr($setVarType), 'offsetSet'),
482482
$scope,
483483
$storage,
484484
new NoopNodeCallback(),

src/Analyser/ExprHandler/IssetHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHPStan\Analyser\NodeScopeResolver;
1818
use PHPStan\Analyser\NoopNodeCallback;
1919
use PHPStan\DependencyInjection\AutowiredService;
20+
use PHPStan\Node\Expr\TypeExpr;
2021
use PHPStan\Type\BooleanType;
2122
use PHPStan\Type\Constant\ConstantBooleanType;
2223
use PHPStan\Type\ObjectType;
@@ -101,7 +102,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
101102

102103
$throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode(
103104
$stmt,
104-
new MethodCall($var->var, 'offsetExists'),
105+
new MethodCall(new TypeExpr($varType), 'offsetExists'),
105106
$scope,
106107
$storage,
107108
new NoopNodeCallback(),

src/Analyser/NodeScopeResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2054,7 +2054,7 @@ public function processStmtNode(
20542054
if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) {
20552055
$throwPoints = array_merge($throwPoints, $this->processExprNode(
20562056
$stmt,
2057-
new MethodCall($var->var, 'offsetUnset'),
2057+
new MethodCall(new TypeExpr($varType), 'offsetUnset'),
20582058
$scope,
20592059
$storage,
20602060
new NoopNodeCallback(),

tests/PHPStan/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRuleTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,26 @@ public function testRule(): void
7070
$this->analyse([__DIR__ . '/data/missing-exception-method-throws.php'], $errors);
7171
}
7272

73+
public function testBugArrayOffset(): void
74+
{
75+
$this->analyse([__DIR__ . '/data/bug-array-offset.php'], [
76+
[
77+
"Method BugArrayOffset\Foo::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.",
78+
19,
79+
],
80+
[
81+
"Method BugArrayOffset\Foo2::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.",
82+
27,
83+
],
84+
[
85+
"Method BugArrayOffset\Foo3::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.",
86+
35,
87+
],
88+
[
89+
"Method BugArrayOffset\Foo4::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.",
90+
43,
91+
],
92+
]);
93+
}
94+
7395
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace BugArrayOffset;
4+
5+
class ParameterNotFoundException extends \Exception {}
6+
7+
interface Container
8+
{
9+
/**
10+
* @throws ParameterNotFoundException
11+
*/
12+
public function getParameter(string $key): mixed;
13+
}
14+
15+
class Foo
16+
{
17+
public function __construct(Container $container)
18+
{
19+
$container->getParameter('shipmonkDeadCode')['debug']['usagesOf'];
20+
}
21+
}
22+
23+
class Foo2
24+
{
25+
public function __construct(Container $container)
26+
{
27+
isset($container->getParameter('shipmonkDeadCode')['debug']['usagesOf']);
28+
}
29+
}
30+
31+
class Foo3
32+
{
33+
public function __construct(Container $container)
34+
{
35+
unset($container->getParameter('shipmonkDeadCode')['debug']['usagesOf']);
36+
}
37+
}
38+
39+
class Foo4
40+
{
41+
public function __construct(Container $container)
42+
{
43+
$container->getParameter('shipmonkDeadCode')['debug']['usagesOf'] = 42;
44+
}
45+
}

0 commit comments

Comments
 (0)