Skip to content

Commit

Permalink
Simulate offsetSet to get throw points for ArrayAccess assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
rajyan committed Mar 9, 2022
1 parent d0ab72a commit 7449b68
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -3286,6 +3286,16 @@ private function processAssignVar(
$nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope);
}
}

if (!(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) {
$throwPoints = array_merge($throwPoints, $this->processExprNode(
new MethodCall($var, 'offsetSet'),
$scope,
static function (): void {
},
$context,
)->getThrowPoints());
}
} elseif ($var instanceof PropertyFetch) {
$objectResult = $this->processExprNode($var->var, $scope, $nodeCallback, $context);
$hasYield = $objectResult->hasYield();
Expand Down
Expand Up @@ -196,6 +196,24 @@ public function testFirstClassCallables(): void
]);
}

public function testBug4852(): void
{
if (!self::$useStaticReflectionProvider) {
$this->markTestSkipped('This test needs static reflection');
}

$this->analyse([__DIR__ . '/data/bug-4852.php'], [
[
'Dead catch - Exception is never thrown in the try block.',
70,
],
[
'Dead catch - Exception is never thrown in the try block.',
77,
],
]);
}

public function testBug5903(): void
{
$this->analyse([__DIR__ . '/data/bug-5903.php'], [
Expand Down
80 changes: 80 additions & 0 deletions tests/PHPStan/Rules/Exceptions/data/bug-4852.php
@@ -0,0 +1,80 @@
<?php

namespace Bug4852;

use ArrayAccess;
use Exception;

final class DefinitelyThrows implements ArrayAccess
{
public function offsetExists ($offset) {}
public function offsetGet ($offset) {}

/**
* @throws Exception
*/
public function offsetSet ($offset , $value) {
throw new Exception();
}
public function offsetUnset ($offset) {}
}

final class MaybeThrows1 implements ArrayAccess
{
public function offsetExists ($offset) {}
public function offsetGet ($offset) {}
public function offsetSet ($offset , $value) {
throw new Exception();
}
public function offsetUnset ($offset) {}
}

class MaybeThrows2 {}

final class DefinitelyNoThrows implements ArrayAccess
{
public function offsetExists ($offset) {}
public function offsetGet ($offset) {}

/**
* @throws void
*/
public function offsetSet ($offset , $value) {}
public function offsetUnset ($offset) {}
}

$foo = new DefinitelyThrows();
try {
$foo[] = 'value';
} catch (Exception $e) {
// not dead
}

$bar = new MaybeThrows1();
try {
$bar[] = 'value';
} catch (Exception $e) {
// not dead
}

$buz = new MaybeThrows2();
try {
$buz[] = 'value';
} catch (Exception $e) {
// not dead
}

$baz = new DefinitelyNoThrows();
try {
$baz[] = 'value';
} catch (Exception $e) {
// dead
}

$array = [];
try {
$array[] = 'value';
} catch (Exception $e) {
// dead
}

0 comments on commit 7449b68

Please sign in to comment.