Skip to content

Commit 53c643d

Browse files
committed
Support for property fetch in initializers
1 parent e4a6d20 commit 53c643d

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

Diff for: src/Reflection/InitializerExprTypeResolver.php

+11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\Node\Expr\BinaryOp;
88
use PhpParser\Node\Expr\ClassConstFetch;
99
use PhpParser\Node\Expr\ConstFetch;
10+
use PhpParser\Node\Expr\PropertyFetch;
1011
use PhpParser\Node\Identifier;
1112
use PhpParser\Node\Name;
1213
use PhpParser\Node\Scalar\DNumber;
@@ -17,6 +18,7 @@
1718
use PhpParser\Node\Scalar\MagicConst\Line;
1819
use PhpParser\Node\Scalar\String_;
1920
use PHPStan\Analyser\ConstantResolver;
21+
use PHPStan\Analyser\OutOfClassScope;
2022
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
2123
use PHPStan\Node\Expr\TypeExpr;
2224
use PHPStan\Php\PhpVersion;
@@ -377,6 +379,15 @@ public function getType(Expr $expr, InitializerExprContext $context): Type
377379
return new ConstantStringType($context->getTraitName(), true);
378380
}
379381

382+
if ($expr instanceof PropertyFetch && $expr->name instanceof Identifier) {
383+
$fetchedOnType = $this->getType($expr->var, $context);
384+
if (!$fetchedOnType->hasProperty($expr->name->name)->yes()) {
385+
return new ErrorType();
386+
}
387+
388+
return $fetchedOnType->getProperty($expr->name->name, new OutOfClassScope())->getReadableType();
389+
}
390+
380391
return new MixedType();
381392
}
382393

Diff for: tests/PHPStan/Analyser/NodeScopeResolverTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,11 @@ public function dataFileAsserts(): iterable
12021202
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
12031203
yield from $this->gatherAssertTypes(__DIR__ . '/data/ibm_db2.php');
12041204
yield from $this->gatherAssertTypes(__DIR__ . '/data/benevolent-union-math.php');
1205+
1206+
if (PHP_VERSION_ID >= 80200) {
1207+
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Constants/data/bug-8957.php');
1208+
}
1209+
12051210
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8956.php');
12061211
}
12071212

Diff for: tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPStan\Rules\MissingTypehintCheck;
66
use PHPStan\Rules\Rule;
77
use PHPStan\Testing\RuleTestCase;
8+
use const PHP_VERSION_ID;
89

910
/**
1011
* @extends RuleTestCase<MissingClassConstantTypehintRule>
@@ -37,4 +38,12 @@ public function testRule(): void
3738
]);
3839
}
3940

41+
public function testBug8957(): void
42+
{
43+
if (PHP_VERSION_ID < 80200) {
44+
$this->markTestSkipped('This test needs PHP 8.2');
45+
}
46+
$this->analyse([__DIR__ . '/data/bug-8957.php'], []);
47+
}
48+
4049
}

Diff for: tests/PHPStan/Rules/Constants/data/bug-8957.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php // lint >= 8.2
2+
3+
namespace Bug8957;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
enum A: string
8+
{
9+
case X = 'x';
10+
case Y = 'y';
11+
}
12+
13+
class B {
14+
public const A = [
15+
A::X->value,
16+
A::Y->value,
17+
];
18+
19+
public function doFoo(): void
20+
{
21+
assertType('array{\'x\', \'y\'}', self::A);
22+
}
23+
}

0 commit comments

Comments
 (0)