Skip to content

Commit

Permalink
Merge pull request #9393 from ygottschalk/fix/9373-using-enum-propert…
Browse files Browse the repository at this point in the history
…y-as-const-array-key

Fix/9373 using enum property as const array key
  • Loading branch information
orklah committed Apr 17, 2023
2 parents 4bc226e + 0a0f900 commit 542d627
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/Psalm/Internal/Codebase/ConstantTypeResolver.php
Expand Up @@ -11,6 +11,9 @@
use Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue;
use Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant;
use Psalm\Internal\Scanner\UnresolvedConstant\Constant;
use Psalm\Internal\Scanner\UnresolvedConstant\EnumNameFetch;
use Psalm\Internal\Scanner\UnresolvedConstant\EnumPropertyFetch;
use Psalm\Internal\Scanner\UnresolvedConstant\EnumValueFetch;
use Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue;
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp;
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBinaryOp;
Expand Down Expand Up @@ -331,6 +334,24 @@ public static function resolve(
}
}

if ($c instanceof EnumPropertyFetch) {
if ($classlikes->enumExists($c->fqcln)) {
$enum_storage = $classlikes->getStorageFor($c->fqcln);
if (isset($enum_storage->enum_cases[$c->case])) {
if ($c instanceof EnumValueFetch) {
$value = $enum_storage->enum_cases[$c->case]->value;
if (is_string($value)) {
return Type::getString($value)->getSingleAtomic();
} elseif (is_int($value)) {
return Type::getInt(false, $value)->getSingleAtomic();
}
} elseif ($c instanceof EnumNameFetch) {
return Type::getString($c->case)->getSingleAtomic();
}
}
}
}

return new TMixed;
}

Expand Down
21 changes: 21 additions & 0 deletions src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php
Expand Up @@ -15,6 +15,8 @@
use Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue;
use Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant;
use Psalm\Internal\Scanner\UnresolvedConstant\Constant;
use Psalm\Internal\Scanner\UnresolvedConstant\EnumNameFetch;
use Psalm\Internal\Scanner\UnresolvedConstant\EnumValueFetch;
use Psalm\Internal\Scanner\UnresolvedConstant\KeyValuePair;
use Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue;
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp;
Expand All @@ -34,6 +36,7 @@
use function class_exists;
use function function_exists;
use function implode;
use function in_array;
use function interface_exists;
use function strtolower;

Expand Down Expand Up @@ -297,6 +300,24 @@ public static function getUnresolvedClassConstExpr(
return new ArrayValue($items);
}

if ($stmt instanceof PhpParser\Node\Expr\PropertyFetch
&& $stmt->var instanceof PhpParser\Node\Expr\ClassConstFetch
&& $stmt->var->class instanceof PhpParser\Node\Name
&& $stmt->var->name instanceof PhpParser\Node\Identifier
&& $stmt->name instanceof PhpParser\Node\Identifier
&& in_array($stmt->name->name, ['name', 'value', true])
) {
$enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
$stmt->var->class,
$aliases,
);
if ($stmt->name->name === 'value') {
return new EnumValueFetch($enum_fq_class_name, $stmt->var->name->name);
} elseif ($stmt->name->name === 'name') {
return new EnumNameFetch($enum_fq_class_name, $stmt->var->name->name);
}
}

return null;
}

Expand Down
11 changes: 11 additions & 0 deletions src/Psalm/Internal/Scanner/UnresolvedConstant/EnumNameFetch.php
@@ -0,0 +1,11 @@
<?php

namespace Psalm\Internal\Scanner\UnresolvedConstant;

/**
* @psalm-immutable
* @internal
*/
class EnumNameFetch extends EnumPropertyFetch
{
}
@@ -0,0 +1,22 @@
<?php

namespace Psalm\Internal\Scanner\UnresolvedConstant;

use Psalm\Internal\Scanner\UnresolvedConstantComponent;

/**
* @psalm-immutable
* @internal
*/
abstract class EnumPropertyFetch extends UnresolvedConstantComponent
{
public string $fqcln;

public string $case;

public function __construct(string $fqcln, string $case)
{
$this->fqcln = $fqcln;
$this->case = $case;
}
}
11 changes: 11 additions & 0 deletions src/Psalm/Internal/Scanner/UnresolvedConstant/EnumValueFetch.php
@@ -0,0 +1,11 @@
<?php

namespace Psalm\Internal\Scanner\UnresolvedConstant;

/**
* @psalm-immutable
* @internal
*/
class EnumValueFetch extends EnumPropertyFetch
{
}

0 comments on commit 542d627

Please sign in to comment.