Skip to content

Commit

Permalink
Merge pull request #8283 from AndrolGenhald/feature/value-of-backed-enum
Browse files Browse the repository at this point in the history
Allow `value-of` to work with backed enums (fixes #7874).
  • Loading branch information
orklah committed Jul 20, 2022
2 parents 33b553e + 66ebf4a commit 85fe7e8
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 64 deletions.
16 changes: 8 additions & 8 deletions UPGRADING.md
Expand Up @@ -42,7 +42,7 @@
- `Psalm\Type\Atomic\TIntRange`
- `Psalm\Type\Atomic\TIterable`
- `Psalm\Type\Atomic\TKeyedArray`
- `Psalm\Type\Atomic\TKeyOfArray`
- `Psalm\Type\Atomic\TKeyOf`
- `Psalm\Type\Atomic\TList`
- `Psalm\Type\Atomic\TLiteralClassString`
- `Psalm\Type\Atomic\TLowercaseString`
Expand All @@ -64,7 +64,7 @@
- `Psalm\Type\Atomic\TTraitString`
- `Psalm\Type\Atomic\TTrue`
- `Psalm\Type\Atomic\TTypeAlias`
- `Psalm\Type\Atomic\TValueOfArray`
- `Psalm\Type\Atomic\TValueOf`
- `Psalm\Type\Atomic\TVoid`
- `Psalm\Type\Union`

Expand Down Expand Up @@ -92,7 +92,7 @@
- `Psalm\Type\Atomic\TInt`
- `Psalm\Type\Atomic\TIterable`
- `Psalm\Type\Atomic\TKeyedArray`
- `Psalm\Type\Atomic\TKeyOfArray`
- `Psalm\Type\Atomic\TKeyOf`
- `Psalm\Type\Atomic\TList`
- `Psalm\Type\Atomic\TLiteralClassString`
- `Psalm\Type\Atomic\TMixed`
Expand All @@ -109,7 +109,7 @@
- `Psalm\Type\Atomic\TTemplateParam`
- `Psalm\Type\Atomic\TTraitString`
- `Psalm\Type\Atomic\TTypeAlias`
- `Psalm\Type\Atomic\TValueOfArray`
- `Psalm\Type\Atomic\TValueOf`
- `Psalm\Type\Atomic\TVoid`
- `Psalm\Type\Union`
- While not a BC break per se, all classes / interfaces / traits / enums under
Expand Down Expand Up @@ -155,8 +155,8 @@
- [BC] Atomic::getId() has now a first param $exact. Calling the method with false will return a less detailed version of the type in some cases (similarly to what `__toString` used to return)
- [BC] To remove a variable from the context, use `Context::remove()`. Calling
`unset($context->vars_in_scope[$var_id])` can cause problems when using references.
- [BC] `TKeyOfClassConstant` has been renamed to `TKeyOfArray`.
- [BC] `TValueOfClassConstant` has been renamed to `TValueOfArray`.
- [BC] `TKeyOfClassConstant` has been renamed to `TKeyOf`.
- [BC] `TValueOfClassConstant` has been renamed to `TValueOf`.
- [BC] `TKeyOfTemplate` base class has been changed from `Scalar` to `Atomic`.
- [BC] Class `Psalm\FileManipulation` became final
- [BC] Class `Psalm\Context` became final
Expand Down Expand Up @@ -742,13 +742,13 @@
- [BC] Class `Psalm\Type\Atomic\TLiteralInt` became final
- [BC] Class `Psalm\Type\Atomic\TTrue` became final
- [BC] Class `Psalm\Type\Atomic\TDependentGetClass` became final
- [BC] Class `Psalm\Type\Atomic\TValueOfArray` became final
- [BC] Class `Psalm\Type\Atomic\TValueOf` became final
- [BC] Class `Psalm\Type\Atomic\TGenericObject` became final
- [BC] Class `Psalm\Type\Atomic\TNonEmptyLowercaseString` became final
- [BC] Class `Psalm\Type\Atomic\TEnumCase` became final
- [BC] Class `Psalm\Type\Atomic\TCallableKeyedArray` became final
- [BC] Class `Psalm\Type\Atomic\TDependentGetDebugType` became final
- [BC] Class `Psalm\Type\Atomic\TKeyOfArray` became final
- [BC] Class `Psalm\Type\Atomic\TKeyOf` became final
- [BC] Class `Psalm\Type\Atomic\TNonspecificLiteralInt` became final
- [BC] Class `Psalm\Type\Atomic\TObjectWithProperties` became final
- [BC] Class `Psalm\Type\Atomic\TTemplateValueOf` became final
Expand Down
8 changes: 4 additions & 4 deletions docs/running_psalm/plugins/plugins_type_system.md
Expand Up @@ -49,15 +49,15 @@ The classes are as follows:

`TIntMaskOf` - as above, but used with a reference to constants in code `int-mask-of<MyClass::CLASS_CONSTANT_*>` will corresponds to `1|2|3|4|5|6|7` if there are three constant 1, 2 and 4

`TKeyOfArray` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).
`TKeyOf` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).

`TValueOfArray` - Represents a value of an array (e.g. `value-of<MyClass::CLASS_CONSTANT>`).
`TValueOf` - Represents a value of an array or enum (e.g. `value-of<MyClass::CLASS_CONSTANT>`).

`TTemplateIndexedAccess` - To be documented

`TTemplateKeyOf` - Represents the type used when using TKeyOfArray when the type of the array is a template
`TTemplateKeyOf` - Represents the type used when using TKeyOf when the type of the array is a template

`TTemplateValueOf` - Represents the type used when using TValueOfArray when the type of the array is a template
`TTemplateValueOf` - Represents the type used when using TValueOf when the type of the array or enum is a template

`TPropertiesOf` - Represents properties and their types of a class as a keyed array (e.g. `properties-of<MyClass>`)

Expand Down
8 changes: 4 additions & 4 deletions src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php
Expand Up @@ -19,7 +19,7 @@
use Psalm\Type\Atomic\TEnumCase;
use Psalm\Type\Atomic\TGenericObject;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TKeyOfArray;
use Psalm\Type\Atomic\TKeyOf;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TLiteralString;
Expand All @@ -36,7 +36,7 @@
use Psalm\Type\Atomic\TTemplateKeyOf;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Atomic\TTemplateValueOf;
use Psalm\Type\Atomic\TValueOfArray;
use Psalm\Type\Atomic\TValueOf;

use function array_merge;
use function array_values;
Expand Down Expand Up @@ -341,7 +341,7 @@ public static function isContainedBy(
}

if ($input_type_part instanceof TTemplateKeyOf) {
$array_key_type = TKeyOfArray::getArrayKeyType($input_type_part->as);
$array_key_type = TKeyOf::getArrayKeyType($input_type_part->as);
if ($array_key_type === null) {
return false;
}
Expand Down Expand Up @@ -375,7 +375,7 @@ public static function isContainedBy(
}

if ($input_type_part instanceof TTemplateValueOf) {
$array_value_type = TValueOfArray::getArrayValueType($input_type_part->as);
$array_value_type = TValueOf::getValueType($input_type_part->as, $codebase);
if ($array_value_type === null) {
return false;
}
Expand Down
12 changes: 6 additions & 6 deletions src/Psalm/Internal/Type/TemplateInferredTypeReplacer.php
Expand Up @@ -11,7 +11,7 @@
use Psalm\Type\Atomic\TConditional;
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TKeyOfArray;
use Psalm\Type\Atomic\TKeyOf;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
Expand All @@ -26,7 +26,7 @@
use Psalm\Type\Atomic\TTemplateParamClass;
use Psalm\Type\Atomic\TTemplatePropertiesOf;
use Psalm\Type\Atomic\TTemplateValueOf;
use Psalm\Type\Atomic\TValueOfArray;
use Psalm\Type\Atomic\TValueOf;
use Psalm\Type\Union;
use UnexpectedValueException;

Expand Down Expand Up @@ -345,15 +345,15 @@ private static function replaceTemplateKeyOfValueOf(
);

if ($atomic_type instanceof TTemplateKeyOf
&& TKeyOfArray::isViableTemplateType($template_type)
&& TKeyOf::isViableTemplateType($template_type)
) {
return new TKeyOfArray(clone $template_type);
return new TKeyOf(clone $template_type);
}

if ($atomic_type instanceof TTemplateValueOf
&& TValueOfArray::isViableTemplateType($template_type)
&& TValueOf::isViableTemplateType($template_type)
) {
return new TValueOfArray(clone $template_type);
return new TValueOf(clone $template_type);
}

return null;
Expand Down
28 changes: 14 additions & 14 deletions src/Psalm/Internal/Type/TypeExpander.php
Expand Up @@ -22,7 +22,7 @@
use Psalm\Type\Atomic\TIntMask;
use Psalm\Type\Atomic\TIntMaskOf;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TKeyOfArray;
use Psalm\Type\Atomic\TKeyOf;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TLiteralClassString;
Expand All @@ -34,7 +34,7 @@
use Psalm\Type\Atomic\TPropertiesOf;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Atomic\TTypeAlias;
use Psalm\Type\Atomic\TValueOfArray;
use Psalm\Type\Atomic\TValueOf;
use Psalm\Type\Atomic\TVoid;
use Psalm\Type\Union;
use ReflectionProperty;
Expand Down Expand Up @@ -363,10 +363,10 @@ public static function expandAtomic(
return [$return_type];
}

if ($return_type instanceof TKeyOfArray
|| $return_type instanceof TValueOfArray
if ($return_type instanceof TKeyOf
|| $return_type instanceof TValueOf
) {
return self::expandKeyOfValueOfArray(
return self::expandKeyOfValueOf(
$codebase,
$return_type,
$self_class,
Expand Down Expand Up @@ -965,11 +965,11 @@ function (?Union $property_type): bool {
}

/**
* @param TKeyOfArray|TValueOfArray $return_type
* @param TKeyOf|TValueOf $return_type
* @param string|TNamedObject|TTemplateParam|null $static_class_type
* @return non-empty-list<Atomic>
*/
private static function expandKeyOfValueOfArray(
private static function expandKeyOfValueOf(
Codebase $codebase,
Atomic &$return_type,
?string $self_class,
Expand Down Expand Up @@ -1025,12 +1025,12 @@ private static function expandKeyOfValueOfArray(

if (!$constant_type
|| (
$return_type instanceof TKeyOfArray
&& !TKeyOfArray::isViableTemplateType($constant_type)
$return_type instanceof TKeyOf
&& !TKeyOf::isViableTemplateType($constant_type)
)
|| (
$return_type instanceof TValueOfArray
&& !TValueOfArray::isViableTemplateType($constant_type)
$return_type instanceof TValueOf
&& !TValueOf::isViableTemplateType($constant_type)
)
) {
if ($throw_on_unresolvable_constant) {
Expand All @@ -1049,10 +1049,10 @@ private static function expandKeyOfValueOfArray(
return [$return_type];
}

if ($return_type instanceof TKeyOfArray) {
$new_return_types = TKeyOfArray::getArrayKeyType(new Union($type_atomics));
if ($return_type instanceof TKeyOf) {
$new_return_types = TKeyOf::getArrayKeyType(new Union($type_atomics));
} else {
$new_return_types = TValueOfArray::getArrayValueType(new Union($type_atomics));
$new_return_types = TValueOf::getValueType(new Union($type_atomics), $codebase);
}
if ($new_return_types === null) {
return [$return_type];
Expand Down
16 changes: 8 additions & 8 deletions src/Psalm/Internal/Type/TypeParser.php
Expand Up @@ -41,7 +41,7 @@
use Psalm\Type\Atomic\TIntMaskOf;
use Psalm\Type\Atomic\TIntRange;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TKeyOfArray;
use Psalm\Type\Atomic\TKeyOf;
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TList;
use Psalm\Type\Atomic\TLiteralClassString;
Expand All @@ -63,7 +63,7 @@
use Psalm\Type\Atomic\TTemplatePropertiesOf;
use Psalm\Type\Atomic\TTemplateValueOf;
use Psalm\Type\Atomic\TTypeAlias;
use Psalm\Type\Atomic\TValueOfArray;
use Psalm\Type\Atomic\TValueOf;
use Psalm\Type\TypeNode;
use Psalm\Type\Union;

Expand Down Expand Up @@ -743,13 +743,13 @@ private static function getTypeFromGenericTree(
);
}

if (!TKeyOfArray::isViableTemplateType($generic_params[0])) {
if (!TKeyOf::isViableTemplateType($generic_params[0])) {
throw new TypeParseTreeException(
'Untemplated key-of param ' . $param_name . ' should be an array'
);
}

return new TKeyOfArray($generic_params[0]);
return new TKeyOf($generic_params[0]);
}

if ($generic_type_value === 'value-of') {
Expand All @@ -765,13 +765,13 @@ private static function getTypeFromGenericTree(
);
}

if (!TValueOfArray::isViableTemplateType($generic_params[0])) {
if (!TValueOf::isViableTemplateType($generic_params[0])) {
throw new TypeParseTreeException(
'Untemplated value-of param ' . $param_name . ' should be an array'
);
}

return new TValueOfArray($generic_params[0]);
return new TValueOf($generic_params[0]);
}

if ($generic_type_value === 'int-mask') {
Expand Down Expand Up @@ -842,8 +842,8 @@ private static function getTypeFromGenericTree(
$param_type = $param_union_types[0];

if (!$param_type instanceof TClassConstant
&& !$param_type instanceof TValueOfArray
&& !$param_type instanceof TKeyOfArray
&& !$param_type instanceof TValueOf
&& !$param_type instanceof TKeyOf
) {
throw new TypeParseTreeException(
'Invalid reference passed to int-mask-of'
Expand Down
4 changes: 2 additions & 2 deletions src/Psalm/Type/Atomic/TIntMaskOf.php
Expand Up @@ -11,11 +11,11 @@
*/
final class TIntMaskOf extends TInt
{
/** @var TClassConstant|TKeyOfArray|TValueOfArray */
/** @var TClassConstant|TKeyOf|TValueOf */
public $value;

/**
* @param TClassConstant|TKeyOfArray|TValueOfArray $value
* @param TClassConstant|TKeyOf|TValueOf $value
*/
public function __construct(Atomic $value)
{
Expand Down
Expand Up @@ -11,7 +11,7 @@
/**
* Represents an offset of an array.
*/
final class TKeyOfArray extends TArrayKey
final class TKeyOf extends TArrayKey
{
/** @var Union */
public $type;
Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Type/Atomic/TTemplateKeyOf.php
Expand Up @@ -9,7 +9,7 @@
use Psalm\Type\Union;

/**
* Represents the type used when using TKeyOfArray when the type of the array is a template
* Represents the type used when using TKeyOf when the type of the array is a template
*/
final class TTemplateKeyOf extends Atomic
{
Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Type/Atomic/TTemplateValueOf.php
Expand Up @@ -9,7 +9,7 @@
use Psalm\Type\Union;

/**
* Represents the type used when using TValueOfArray when the type of the array is a template
* Represents the type used when using TValueOf when the type of the array or enum is a template
*/
final class TTemplateValueOf extends Atomic
{
Expand Down

0 comments on commit 85fe7e8

Please sign in to comment.