diff --git a/src/AtClass.php b/src/AtClass.php new file mode 100644 index 0000000..9a3d84f --- /dev/null +++ b/src/AtClass.php @@ -0,0 +1,28 @@ +name = $name; + } +} diff --git a/src/AtFunction.php b/src/AtFunction.php new file mode 100644 index 0000000..c7b3e85 --- /dev/null +++ b/src/AtFunction.php @@ -0,0 +1,28 @@ +name = $name; + } +} diff --git a/src/AtMethod.php b/src/AtMethod.php new file mode 100644 index 0000000..132a190 --- /dev/null +++ b/src/AtMethod.php @@ -0,0 +1,36 @@ +class = $class; + $this->name = $name; + } +} diff --git a/src/StaticType.php b/src/StaticType.php index 10c94e9..b96c415 100644 --- a/src/StaticType.php +++ b/src/StaticType.php @@ -12,6 +12,11 @@ */ final class StaticType implements Type { + /** + * @var class-string + */ + public readonly string $declaredAtClass; + /** * @var list */ @@ -21,11 +26,14 @@ final class StaticType implements Type * @internal * @psalm-internal Typhoon\Type * @no-named-arguments + * @param class-string $declaredAtClass * @param list $templateArguments */ public function __construct( + string $declaredAtClass, array $templateArguments = [], ) { + $this->declaredAtClass = $declaredAtClass; $this->templateArguments = $templateArguments; } diff --git a/src/TemplateType.php b/src/TemplateType.php index 916cec7..43f4d34 100644 --- a/src/TemplateType.php +++ b/src/TemplateType.php @@ -17,15 +17,27 @@ final class TemplateType implements Type */ public readonly string $name; + public readonly AtMethod|AtClass|AtFunction $declaredAt; + + /** + * @var Type + */ + public readonly Type $constraint; + /** * @internal * @psalm-internal Typhoon\Type * @param non-empty-string $name + * @param Type $constraint */ public function __construct( string $name, + AtFunction|AtClass|AtMethod $declaredAt, + Type $constraint, ) { $this->name = $name; + $this->declaredAt = $declaredAt; + $this->constraint = $constraint; } public function accept(TypeVisitor $visitor): mixed diff --git a/src/types.php b/src/types.php index 8ffaf18..2055dd3 100644 --- a/src/types.php +++ b/src/types.php @@ -265,10 +265,13 @@ public static function object(string $class, Type ...$templateArguments): NamedO /** * @psalm-pure * @no-named-arguments + * @template TObject of object + * @param class-string $declaredAtClass + * @return StaticType */ - public static function static(Type ...$templateArguments): StaticType + public static function static(string $declaredAtClass, Type ...$templateArguments): StaticType { - return new StaticType($templateArguments); + return new StaticType($declaredAtClass, $templateArguments); } /** @@ -367,11 +370,39 @@ public static function valueOf(Type $type): ValueOfType /** * @psalm-pure + * @template TType + * @param non-empty-string $name + * @param Type $constraint + * @return TemplateType + */ + public static function template(string $name, AtMethod|AtClass|AtFunction $declaredAt, Type $constraint = self::mixed): TemplateType + { + return new TemplateType($name, $declaredAt, $constraint); + } + + /** + * @param callable-string $name + */ + public static function atFunction(string $name): AtFunction + { + return new AtFunction($name); + } + + /** + * @param class-string $name + */ + public static function atClass(string $name): AtClass + { + return new AtClass($name); + } + + /** + * @param class-string $class * @param non-empty-string $name */ - public static function template(string $name): TemplateType + public static function atMethod(string $class, string $name): AtMethod { - return new TemplateType($name); + return new AtMethod($class, $name); } /** diff --git a/tests/psalm/StaticType.phpt b/tests/psalm/StaticType.phpt index a6ecbd8..af7b233 100644 --- a/tests/psalm/StaticType.phpt +++ b/tests/psalm/StaticType.phpt @@ -3,7 +3,7 @@ namespace Typhoon\Type; -$_type = PsalmTest::extractType(new StaticType()); -/** @psalm-check-type-exact $_type = \object */ +$_type = PsalmTest::extractType(new StaticType(\stdClass::class)); +/** @psalm-check-type-exact $_type = \stdClass */ --EXPECT-- diff --git a/tests/psalm/TemplateType.phpt b/tests/psalm/TemplateType.phpt index 501e025..1042e36 100644 --- a/tests/psalm/TemplateType.phpt +++ b/tests/psalm/TemplateType.phpt @@ -3,7 +3,7 @@ namespace Typhoon\Type; -$_type = PsalmTest::extractType(new TemplateType('T')); -/** @psalm-check-type-exact $_type = \mixed */ +$_type = PsalmTest::extractType(new TemplateType('T', new AtFunction('trim'), ObjectType::type)); +/** @psalm-check-type-exact $_type = \object */ --EXPECT--