diff --git a/src/Analyser/ExprHandler/ArrayDimFetchHandler.php b/src/Analyser/ExprHandler/ArrayDimFetchHandler.php index 224bf4142d..beb6d991a0 100644 --- a/src/Analyser/ExprHandler/ArrayDimFetchHandler.php +++ b/src/Analyser/ExprHandler/ArrayDimFetchHandler.php @@ -18,6 +18,7 @@ use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\NoopNodeCallback; use PHPStan\DependencyInjection\AutowiredService; +use PHPStan\Node\Expr\TypeExpr; use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -99,7 +100,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode( $stmt, - new MethodCall($expr->var, 'offsetGet'), + new MethodCall(new TypeExpr($varType), 'offsetGet'), $scope, $storage, new NoopNodeCallback(), diff --git a/src/Analyser/ExprHandler/AssignHandler.php b/src/Analyser/ExprHandler/AssignHandler.php index 284ec47619..76c40b1ae3 100644 --- a/src/Analyser/ExprHandler/AssignHandler.php +++ b/src/Analyser/ExprHandler/AssignHandler.php @@ -478,7 +478,7 @@ public function processAssignVar( ) { $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode( $stmt, - new MethodCall($originalVar->var, 'offsetSet'), + new MethodCall(new TypeExpr($setVarType), 'offsetSet'), $scope, $storage, new NoopNodeCallback(), diff --git a/src/Analyser/ExprHandler/IssetHandler.php b/src/Analyser/ExprHandler/IssetHandler.php index 581ee9af78..d794bea909 100644 --- a/src/Analyser/ExprHandler/IssetHandler.php +++ b/src/Analyser/ExprHandler/IssetHandler.php @@ -17,6 +17,7 @@ use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\NoopNodeCallback; use PHPStan\DependencyInjection\AutowiredService; +use PHPStan\Node\Expr\TypeExpr; use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\ObjectType; @@ -101,7 +102,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $throwPoints = array_merge($throwPoints, $nodeScopeResolver->processExprNode( $stmt, - new MethodCall($var->var, 'offsetExists'), + new MethodCall(new TypeExpr($varType), 'offsetExists'), $scope, $storage, new NoopNodeCallback(), diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8a112cda54..79b05cd0f8 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -2054,7 +2054,7 @@ public function processStmtNode( if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { $throwPoints = array_merge($throwPoints, $this->processExprNode( $stmt, - new MethodCall($var->var, 'offsetUnset'), + new MethodCall(new TypeExpr($varType), 'offsetUnset'), $scope, $storage, new NoopNodeCallback(), diff --git a/tests/PHPStan/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRuleTest.php b/tests/PHPStan/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRuleTest.php index aee538052e..c3e548bf0e 100644 --- a/tests/PHPStan/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRuleTest.php @@ -70,4 +70,26 @@ public function testRule(): void $this->analyse([__DIR__ . '/data/missing-exception-method-throws.php'], $errors); } + public function testBugArrayOffset(): void + { + $this->analyse([__DIR__ . '/data/bug-array-offset.php'], [ + [ + "Method BugArrayOffset\Foo::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.", + 19, + ], + [ + "Method BugArrayOffset\Foo2::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.", + 27, + ], + [ + "Method BugArrayOffset\Foo3::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.", + 35, + ], + [ + "Method BugArrayOffset\Foo4::__construct() throws checked exception BugArrayOffset\ParameterNotFoundException but it's missing from the PHPDoc @throws tag.", + 43, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Exceptions/data/bug-array-offset.php b/tests/PHPStan/Rules/Exceptions/data/bug-array-offset.php new file mode 100644 index 0000000000..35bf9543e8 --- /dev/null +++ b/tests/PHPStan/Rules/Exceptions/data/bug-array-offset.php @@ -0,0 +1,45 @@ +getParameter('shipmonkDeadCode')['debug']['usagesOf']; + } +} + +class Foo2 +{ + public function __construct(Container $container) + { + isset($container->getParameter('shipmonkDeadCode')['debug']['usagesOf']); + } +} + +class Foo3 +{ + public function __construct(Container $container) + { + unset($container->getParameter('shipmonkDeadCode')['debug']['usagesOf']); + } +} + +class Foo4 +{ + public function __construct(Container $container) + { + $container->getParameter('shipmonkDeadCode')['debug']['usagesOf'] = 42; + } +}