Skip to content

Commit

Permalink
Type: fixed resolving of 'static'
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 20, 2023
1 parent cead663 commit d152fe2
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/Utils/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,33 @@ final class Type
*/
public static function fromReflection(
\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection,
?\ReflectionClass $staticClass = null,
): ?self
{
$type = $reflection instanceof \ReflectionFunctionAbstract
? $reflection->getReturnType() ?? (PHP_VERSION_ID >= 80100 && $reflection instanceof \ReflectionMethod ? $reflection->getTentativeReturnType() : null)
: $reflection->getType();

return $type ? self::fromReflectionType($type, $reflection, true) : null;
return $type ? self::fromReflectionType($type, $reflection, true, $staticClass) : null;
}


private static function fromReflectionType(\ReflectionType $type, $of, bool $asObject): self|string
private static function fromReflectionType(
\ReflectionType $type,
$of,
bool $asObject,
?\ReflectionClass $staticClass,
): self|string
{
if ($type instanceof \ReflectionNamedType) {
$name = self::resolve($type->getName(), $of);
$name = self::resolve($type->getName(), $of, $staticClass);
return $asObject
? new self($type->allowsNull() && $name !== 'mixed' ? [$name, 'null'] : [$name])
: $name;

} elseif ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) {
return new self(
array_map(fn($t) => self::fromReflectionType($t, $of, false), $type->getTypes()),
array_map(fn($t) => self::fromReflectionType($t, $of, false, $staticClass), $type->getTypes()),
$type instanceof \ReflectionUnionType ? '|' : '&',
);

Expand Down Expand Up @@ -90,13 +96,16 @@ public static function fromString(string $type): self
public static function resolve(
string $type,
\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $of,
?\ReflectionClass $staticClass = null,
): string
{
$lower = strtolower($type);
if ($of instanceof \ReflectionFunction) {
return $type;
} elseif ($lower === 'self' || $lower === 'static') {
} elseif ($lower === 'self') {
return $of->getDeclaringClass()->name;
} elseif ($lower === 'static') {
return ($staticClass ?? $of->getDeclaringClass())->name;
} elseif ($lower === 'parent' && $of->getDeclaringClass()->getParentClass()) {
return $of->getDeclaringClass()->getParentClass()->name;
} else {
Expand Down
16 changes: 16 additions & 0 deletions tests/Utils/Type.fromReflection.method.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,19 @@ $type = Type::fromReflection((new ReflectionObject($class))->getMethod('foo'));

Assert::same([$class::class], $type->getNames());
Assert::same($class::class, (string) $type);


class ParentClass
{
public function foo(): static
{
}
}

class ChildClass extends ParentClass
{
}

$type = Type::fromReflection(new ReflectionMethod(ChildClass::class, 'foo'), new ReflectionClass(ChildClass::class));
Assert::same([ChildClass::class], $type->getNames());
Assert::same(ChildClass::class, (string) $type);

0 comments on commit d152fe2

Please sign in to comment.