diff --git a/psalm.xml b/psalm.xml
index bb4ac1f..71e33ca 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -1,14 +1,17 @@
+
@@ -30,6 +33,11 @@
+
+
+
+
+
diff --git a/src/Doctrine/PlatenumDoctrineType.php b/src/Doctrine/PlatenumDoctrineType.php
index 8c194fc..586e438 100644
--- a/src/Doctrine/PlatenumDoctrineType.php
+++ b/src/Doctrine/PlatenumDoctrineType.php
@@ -6,7 +6,10 @@
use Doctrine\DBAL\Types\Type;
use Thunder\Platenum\Enum\EnumTrait;
-/** @psalm-suppress PropertyNotSetInConstructor, MissingConstructor */
+/**
+ * @psalm-suppress PropertyNotSetInConstructor, MissingConstructor
+ * @psalm-external-mutation-free
+ */
final class PlatenumDoctrineType extends Type
{
/** @var class-string */
@@ -107,6 +110,7 @@ public function getName(): string
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
+ /** @psalm-suppress ImpureFunctionCall */
return ($this->platenumSql)($column, $platform);
}
@@ -120,7 +124,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform)
throw new \LogicException(sprintf($message, self::class, gettype($value)));
}
- /** @psalm-suppress MixedMethodCall */
+ /** @psalm-suppress MixedMethodCall,ImpureFunctionCall */
return ($this->platenumCallback)($value->getValue());
}
@@ -130,7 +134,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform)
return null;
}
- /** @psalm-suppress MixedMethodCall */
+ /** @psalm-suppress MixedMethodCall,ImpureFunctionCall */
return ($this->platenumClass)::fromValue(($this->platenumCallback)($value));
}
diff --git a/src/Enum/AbstractCallbackEnum.php b/src/Enum/AbstractCallbackEnum.php
index 49d812f..6543a16 100644
--- a/src/Enum/AbstractCallbackEnum.php
+++ b/src/Enum/AbstractCallbackEnum.php
@@ -4,8 +4,11 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
abstract class AbstractCallbackEnum implements \JsonSerializable
{
+ /** @use CallbackEnumTrait */
use CallbackEnumTrait;
}
diff --git a/src/Enum/AbstractConstantsEnum.php b/src/Enum/AbstractConstantsEnum.php
index 696b0d6..cb3faf4 100644
--- a/src/Enum/AbstractConstantsEnum.php
+++ b/src/Enum/AbstractConstantsEnum.php
@@ -4,8 +4,11 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
abstract class AbstractConstantsEnum implements \JsonSerializable
{
+ /** @use ConstantsEnumTrait */
use ConstantsEnumTrait;
}
diff --git a/src/Enum/AbstractDocblockEnum.php b/src/Enum/AbstractDocblockEnum.php
index d7d994c..2ae7bc8 100644
--- a/src/Enum/AbstractDocblockEnum.php
+++ b/src/Enum/AbstractDocblockEnum.php
@@ -4,8 +4,11 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
abstract class AbstractDocblockEnum implements \JsonSerializable
{
+ /** @use DocblockEnumTrait */
use DocblockEnumTrait;
}
diff --git a/src/Enum/AbstractStaticEnum.php b/src/Enum/AbstractStaticEnum.php
index 6f347fa..fb16bb2 100644
--- a/src/Enum/AbstractStaticEnum.php
+++ b/src/Enum/AbstractStaticEnum.php
@@ -4,9 +4,12 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
abstract class AbstractStaticEnum implements \JsonSerializable
{
+ /** @use StaticEnumTrait */
use StaticEnumTrait;
/** @var array */
diff --git a/src/Enum/CallbackEnumTrait.php b/src/Enum/CallbackEnumTrait.php
index 6c8b773..a45cf07 100644
--- a/src/Enum/CallbackEnumTrait.php
+++ b/src/Enum/CallbackEnumTrait.php
@@ -6,9 +6,12 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
trait CallbackEnumTrait
{
+ /** @use EnumTrait */
use EnumTrait;
/** @var non-empty-array> */
diff --git a/src/Enum/ConstantsEnumTrait.php b/src/Enum/ConstantsEnumTrait.php
index 4a1aea5..4930e1f 100644
--- a/src/Enum/ConstantsEnumTrait.php
+++ b/src/Enum/ConstantsEnumTrait.php
@@ -4,9 +4,12 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
trait ConstantsEnumTrait
{
+ /** @use EnumTrait */
use EnumTrait;
private static function resolve(): array
diff --git a/src/Enum/DocblockEnumTrait.php b/src/Enum/DocblockEnumTrait.php
index 0784a7d..5bf71b4 100644
--- a/src/Enum/DocblockEnumTrait.php
+++ b/src/Enum/DocblockEnumTrait.php
@@ -6,9 +6,12 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
trait DocblockEnumTrait
{
+ /** @use EnumTrait */
use EnumTrait;
private static function resolve(): array
diff --git a/src/Enum/EnumTrait.php b/src/Enum/EnumTrait.php
index 6bd7e27..0a7b514 100644
--- a/src/Enum/EnumTrait.php
+++ b/src/Enum/EnumTrait.php
@@ -6,20 +6,22 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
trait EnumTrait
{
/** @var string */
private $member;
- /** @var int|string */
+ /** @psalm-var T */
private $value;
- /** @var non-empty-array> */
+ /** @psalm-var non-empty-array> */
protected static $members = [];
/** @var array> */
protected static $instances = [];
- /** @param int|string $value */
+ /** @psalm-param T $value */
/* final */ private function __construct(string $member, $value)
{
$this->member = $member;
@@ -51,8 +53,18 @@ final public static function fromMember(string $member): self
static::throwDefaultInvalidMemberException($member);
}
+ /** @psalm-suppress PropertyTypeCoercion */
+ return static::$instances[$class][$member] = static::fromMemberAndValue($member, static::$members[$class][$member]);
+ }
+
+ /**
+ * @psalm-param int|string $value
+ * @psalm-return static
+ */
+ /* final */ private static function fromMemberAndValue(string $member, $value): self
+ {
/** @psalm-suppress UnsafeInstantiation */
- return static::$instances[$class][$member] = new static($member, static::$members[$class][$member]);
+ return new static($member, $value);
}
/**
@@ -91,12 +103,15 @@ final public static function fromEnum($enum): self
}
/**
- * @param static $enum
- * @param-out AbstractConstantsEnum|AbstractDocblockEnum|AbstractStaticEnum|AbstractCallbackEnum|AbstractAttributeEnum $enum
+ * @param self &$enum
+ * @param-out self $enum
+ * @psalm-suppress ReferenceConstraintViolation
*/
final public function fromInstance(&$enum): void
{
- $enum = static::fromEnum($enum);
+ /** @psalm-suppress ImpureMethodCall,ArgumentTypeCoercion */
+ $instance = static::fromEnum($enum);
+ $enum = $instance;
}
/**
@@ -154,12 +169,13 @@ final public function getMember(): string
return $this->member;
}
- /** @return int|string */
+ /** @psalm-return T */
final public function getValue()
{
return $this->value;
}
+ /** @psalm-return T */
#[\ReturnTypeWillChange]
final public function jsonSerialize()
{
@@ -209,7 +225,7 @@ final public function hasMember(string $members): bool
return $members === $this->member;
}
- /** @param int|string $value */
+ /** @psalm-param T $value */
final public function hasValue($value): bool
{
return $value === $this->value;
@@ -293,7 +309,7 @@ private static function resolveMembers(): void
// reflection instead of method_exists because of PHP 7.4 bug #78632
// @see https://bugs.php.net/bug.php?id=78632
$hasResolve = (new \ReflectionClass($class))->hasMethod('resolve');
- /** @var array $members */
+ /** @psalm-var array $members */
$members = $hasResolve ? static::resolve() : $throwMissingResolve($class);
if(empty($members)) {
throw PlatenumException::fromEmptyMembers($class);
@@ -308,6 +324,7 @@ private static function resolveMembers(): void
throw PlatenumException::fromNonUniformMemberValues($class, $members);
}
+ /** @psalm-suppress MixedPropertyTypeCoercion */
static::$members[$class] = $members;
}
diff --git a/src/Enum/StaticEnumTrait.php b/src/Enum/StaticEnumTrait.php
index 738cee2..01a54eb 100644
--- a/src/Enum/StaticEnumTrait.php
+++ b/src/Enum/StaticEnumTrait.php
@@ -6,9 +6,12 @@
/**
* @author Tomasz Kowalczyk
+ * @psalm-template T
+ * @psalm-immutable
*/
trait StaticEnumTrait
{
+ /** @use EnumTrait */
use EnumTrait;
private static function resolve(): array
diff --git a/tests/Psalm/PsalmConstantsExtendsEnum.php b/tests/Psalm/PsalmConstantsExtendsEnum.php
new file mode 100644
index 0000000..54be986
--- /dev/null
+++ b/tests/Psalm/PsalmConstantsExtendsEnum.php
@@ -0,0 +1,18 @@
+
+ * @psalm-immutable
+ * @psalm-suppress PropertyNotSetInConstructor
+ */
+final class PsalmConstantsExtendsEnum extends AbstractConstantsEnum
+{
+ public const FIRST = 1;
+ public const SECOND = 2;
+}
diff --git a/tests/Psalm/PsalmConstantsTraitEnum.php b/tests/Psalm/PsalmConstantsTraitEnum.php
new file mode 100644
index 0000000..d9e06e8
--- /dev/null
+++ b/tests/Psalm/PsalmConstantsTraitEnum.php
@@ -0,0 +1,20 @@
+ */
+ use ConstantsEnumTrait;
+
+ public const FIRST = 1;
+ public const SECOND = 2;
+}
diff --git a/tests/Psalm/PsalmEnum.php b/tests/Psalm/PsalmEnum.php
new file mode 100644
index 0000000..7c465c6
--- /dev/null
+++ b/tests/Psalm/PsalmEnum.php
@@ -0,0 +1,17 @@
+