Skip to content

Commit 0a4b3b5

Browse files
committed
Merge branch 2.1.x into 2.2.x
2 parents 15c5a85 + 22923ac commit 0a4b3b5

6 files changed

Lines changed: 105 additions & 0 deletions

File tree

src/Analyser/MutatingScope.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,14 @@ public function issetCheck(Expr $expr, callable $typeCallback, ?bool $result = n
10891089
}
10901090

10911091
if ($result !== null) {
1092+
if ($expr instanceof Node\Expr\PropertyFetch) {
1093+
return $this->issetCheck($expr->var, $typeCallback, $result);
1094+
}
1095+
1096+
if ($expr->class instanceof Expr) {
1097+
return $this->issetCheck($expr->class, $typeCallback, $result);
1098+
}
1099+
10921100
return $result;
10931101
}
10941102

src/Rules/IssetCheck.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ static function (Type $type) use ($typeMessageCallback): ?string {
196196
$propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $expr);
197197
$propertyType = $propertyReflection->getWritableType();
198198
if ($error !== null) {
199+
if ($expr instanceof Node\Expr\PropertyFetch) {
200+
return $this->check($expr->var, $scope, $operatorDescription, $identifier, $typeMessageCallback, $error);
201+
}
202+
203+
if ($expr->class instanceof Expr) {
204+
return $this->check($expr->class, $scope, $operatorDescription, $identifier, $typeMessageCallback, $error);
205+
}
206+
199207
return $error;
200208
}
201209
if (!$this->checkAdvancedIsset) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug14555Nsrt;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
class ValueObject {
10+
function __construct(
11+
public readonly string $value,
12+
) {}
13+
}
14+
15+
class SomeDTO {
16+
function __construct(
17+
public readonly ValueObject $value,
18+
) {}
19+
}
20+
21+
/** @param array<string, list<SomeDTO>> $array */
22+
function testCoalesceType(array $array): void
23+
{
24+
$someValue = $array['someKey'][0]->value->value ?? null;
25+
assertType('string|null', $someValue);
26+
}

tests/PHPStan/Rules/Variables/IssetRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,13 @@ public function testBug9503(): void
531531
$this->analyse([__DIR__ . '/data/bug-9503.php'], []);
532532
}
533533

534+
public function testBug14555(): void
535+
{
536+
$this->treatPhpDocTypesAsCertain = true;
537+
538+
$this->analyse([__DIR__ . '/data/bug-14555.php'], []);
539+
}
540+
534541
public function testBug14393(): void
535542
{
536543
$this->treatPhpDocTypesAsCertain = true;

tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ public function testBug14458(): void
397397
$this->analyse([__DIR__ . '/data/bug-14458.php'], []);
398398
}
399399

400+
#[RequiresPhp('>= 8.1.0')]
401+
public function testBug14555(): void
402+
{
403+
$this->analyse([__DIR__ . '/data/bug-14555.php'], []);
404+
}
405+
400406
#[RequiresPhp('>= 8.1.0')]
401407
public function testBug14459(): void
402408
{
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug14555;
6+
7+
class ValueObject {
8+
function __construct(
9+
public readonly string $value,
10+
) {}
11+
}
12+
13+
class SomeDTO {
14+
function __construct(
15+
public readonly ValueObject $value,
16+
) {}
17+
}
18+
19+
class StaticHolder {
20+
public static ValueObject $value;
21+
}
22+
23+
/** @param array<string, list<SomeDTO>> $array */
24+
function exampleNullCoalesce(array $array): void
25+
{
26+
$someValue = $array['someKey'][0]->value->value ?? null;
27+
28+
$dto = $array['someKey'][0] ?? null;
29+
$someValue2 = $dto->value->value ?? null;
30+
}
31+
32+
/** @param array<string, list<SomeDTO>> $array */
33+
function exampleIsset(array $array): void
34+
{
35+
if (isset($array['someKey'][0]->value->value)) {
36+
echo 'yes';
37+
}
38+
}
39+
40+
/** @param array<string, list<SomeDTO>> $array */
41+
function exampleNullCoalesceAssign(array $array): void
42+
{
43+
$someValue = $array['someKey'][0]->value->value ??= 'default';
44+
}
45+
46+
/** @param array<string, list<StaticHolder>> $array */
47+
function exampleStaticProperty(array $array): void
48+
{
49+
$someValue = $array['someKey'][0]::$value->value ?? null;
50+
}

0 commit comments

Comments
 (0)