Skip to content

Commit

Permalink
Support for property fetch in initializers
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 25, 2023
1 parent e4a6d20 commit 53c643d
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/Reflection/InitializerExprTypeResolver.php
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\DNumber;
Expand All @@ -17,6 +18,7 @@
use PhpParser\Node\Scalar\MagicConst\Line;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\ConstantResolver;
use PHPStan\Analyser\OutOfClassScope;
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
use PHPStan\Node\Expr\TypeExpr;
use PHPStan\Php\PhpVersion;
Expand Down Expand Up @@ -377,6 +379,15 @@ public function getType(Expr $expr, InitializerExprContext $context): Type
return new ConstantStringType($context->getTraitName(), true);
}

if ($expr instanceof PropertyFetch && $expr->name instanceof Identifier) {
$fetchedOnType = $this->getType($expr->var, $context);
if (!$fetchedOnType->hasProperty($expr->name->name)->yes()) {
return new ErrorType();
}

return $fetchedOnType->getProperty($expr->name->name, new OutOfClassScope())->getReadableType();
}

return new MixedType();
}

Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1202,6 +1202,11 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/ibm_db2.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/benevolent-union-math.php');

if (PHP_VERSION_ID >= 80200) {
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Constants/data/bug-8957.php');
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8956.php');
}

Expand Down
Expand Up @@ -5,6 +5,7 @@
use PHPStan\Rules\MissingTypehintCheck;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use const PHP_VERSION_ID;

/**
* @extends RuleTestCase<MissingClassConstantTypehintRule>
Expand Down Expand Up @@ -37,4 +38,12 @@ public function testRule(): void
]);
}

public function testBug8957(): void
{
if (PHP_VERSION_ID < 80200) {
$this->markTestSkipped('This test needs PHP 8.2');
}
$this->analyse([__DIR__ . '/data/bug-8957.php'], []);
}

}
23 changes: 23 additions & 0 deletions tests/PHPStan/Rules/Constants/data/bug-8957.php
@@ -0,0 +1,23 @@
<?php // lint >= 8.2

namespace Bug8957;

use function PHPStan\Testing\assertType;

enum A: string
{
case X = 'x';
case Y = 'y';
}

class B {
public const A = [
A::X->value,
A::Y->value,
];

public function doFoo(): void
{
assertType('array{\'x\', \'y\'}', self::A);
}
}

0 comments on commit 53c643d

Please sign in to comment.