-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP introduced Psalm templates with ability to restrict possible valu…
…es on type level
- Loading branch information
Showing
12 changed files
with
97 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,11 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
abstract class AbstractCallbackEnum implements \JsonSerializable | ||
{ | ||
/** @use CallbackEnumTrait<T> */ | ||
use CallbackEnumTrait; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,11 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
abstract class AbstractConstantsEnum implements \JsonSerializable | ||
{ | ||
/** @use ConstantsEnumTrait<T> */ | ||
use ConstantsEnumTrait; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,11 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
abstract class AbstractDocblockEnum implements \JsonSerializable | ||
{ | ||
/** @use DocblockEnumTrait<T> */ | ||
use DocblockEnumTrait; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,12 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
abstract class AbstractStaticEnum implements \JsonSerializable | ||
{ | ||
/** @use StaticEnumTrait<T> */ | ||
use StaticEnumTrait; | ||
|
||
/** @var array */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,12 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
trait CallbackEnumTrait | ||
{ | ||
/** @use EnumTrait<T> */ | ||
use EnumTrait; | ||
|
||
/** @var non-empty-array<class-string,callable():array<string,int|string>> */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,12 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
trait ConstantsEnumTrait | ||
{ | ||
/** @use EnumTrait<T> */ | ||
use EnumTrait; | ||
|
||
private static function resolve(): array | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,12 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
trait DocblockEnumTrait | ||
{ | ||
/** @use EnumTrait<T> */ | ||
use EnumTrait; | ||
|
||
private static function resolve(): array | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,20 +6,22 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
trait EnumTrait | ||
{ | ||
/** @var string */ | ||
private $member; | ||
/** @var int|string */ | ||
/** @psalm-var T */ | ||
private $value; | ||
|
||
/** @var non-empty-array<string,non-empty-array<string,int|string>> */ | ||
/** @psalm-var non-empty-array<string,non-empty-array<string,int|string>> */ | ||
protected static $members = []; | ||
/** @var array<string,array<string,static>> */ | ||
protected static $instances = []; | ||
|
||
/** @param int|string $value */ | ||
/** @psalm-param T $value */ | ||
final private function __construct(string $member, $value) | ||
{ | ||
$this->member = $member; | ||
|
@@ -51,8 +53,17 @@ final public static function fromMember(string $member): self | |
static::throwDefaultInvalidMemberException($member); | ||
} | ||
|
||
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,8 +102,8 @@ 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 | ||
*/ | ||
final public function fromInstance(&$enum): void | ||
{ | ||
|
@@ -140,12 +151,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() | ||
{ | ||
|
@@ -179,7 +191,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; | ||
|
@@ -245,7 +257,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<string,int|string> $members */ | ||
/** @psalm-var array<string,T> $members */ | ||
$members = $hasResolve ? static::resolve() : $throwMissingResolve($class); | ||
if(empty($members)) { | ||
throw PlatenumException::fromEmptyMembers($class); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,12 @@ | |
|
||
/** | ||
* @author Tomasz Kowalczyk <[email protected]> | ||
* @psalm-template T | ||
* @psalm-immutable | ||
*/ | ||
trait StaticEnumTrait | ||
{ | ||
/** @use EnumTrait<T> */ | ||
use EnumTrait; | ||
|
||
private static function resolve(): array | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
declare(strict_types=1); | ||
namespace Thunder\Platenum\Tests\Psalm; | ||
|
||
use Thunder\Platenum\Enum\AbstractConstantsEnum; | ||
use Thunder\Platenum\Enum\ConstantsEnumTrait; | ||
|
||
final class PsalmEnum | ||
{ | ||
} | ||
|
||
/** | ||
* @method static static FIRST() | ||
* @method static static SECOND() | ||
* @psalm-template T of self::* | ||
* @psalm-immutable | ||
*/ | ||
final class PsalmConstantsTraitEnum | ||
{ | ||
/** @use ConstantsEnumTrait<T> */ | ||
use ConstantsEnumTrait; | ||
|
||
public const FIRST = 1; | ||
public const SECOND = 2; | ||
} | ||
|
||
PsalmConstantsTraitEnum::FIRST(); | ||
PsalmConstantsTraitEnum::SECOND(); | ||
PsalmConstantsTraitEnum::fromMember('THIRD'); | ||
PsalmConstantsTraitEnum::fromValue(4); | ||
|
||
/** | ||
* @method static static FIRST() | ||
* @method static static SECOND() | ||
* @psalm-template T of self::* | ||
* @psalm-immutable | ||
*/ | ||
final class PsalmConstantsExtendsEnum extends AbstractConstantsEnum | ||
{ | ||
public const FIRST = 1; | ||
public const SECOND = 2; | ||
} | ||
|
||
PsalmConstantsExtendsEnum::FIRST(); | ||
PsalmConstantsExtendsEnum::SECOND(); | ||
PsalmConstantsExtendsEnum::fromMember('THIRD'); | ||
PsalmConstantsExtendsEnum::fromValue(4); |