mirror of
https://github.com/danog/Valinor.git
synced 2024-11-30 04:39:05 +01:00
fix: handle inherited private constructor in class definition
This commit is contained in:
parent
2b46a60f37
commit
73b62241b6
@ -9,6 +9,7 @@ use CuyZ\Valinor\Definition\Exception\ClassTypeAliasesDuplication;
|
||||
use CuyZ\Valinor\Definition\Exception\InvalidTypeAliasImportClass;
|
||||
use CuyZ\Valinor\Definition\Exception\InvalidTypeAliasImportClassType;
|
||||
use CuyZ\Valinor\Definition\Exception\UnknownTypeAliasImport;
|
||||
use CuyZ\Valinor\Definition\MethodDefinition;
|
||||
use CuyZ\Valinor\Definition\Methods;
|
||||
use CuyZ\Valinor\Definition\Properties;
|
||||
use CuyZ\Valinor\Definition\Repository\AttributesRepository;
|
||||
@ -24,7 +25,7 @@ use CuyZ\Valinor\Type\Type;
|
||||
use CuyZ\Valinor\Type\Types\ClassType;
|
||||
use CuyZ\Valinor\Type\Types\UnresolvableType;
|
||||
use CuyZ\Valinor\Utility\Reflection\Reflection;
|
||||
use ReflectionMethod;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function array_filter;
|
||||
@ -61,19 +62,40 @@ final class ReflectionClassDefinitionRepository implements ClassDefinitionReposi
|
||||
$reflection->getProperties()
|
||||
);
|
||||
|
||||
$methods = array_map(
|
||||
fn (ReflectionMethod $method) => $this->methodBuilder->for($method, $typeResolver),
|
||||
$reflection->getMethods()
|
||||
);
|
||||
|
||||
return new ClassDefinition(
|
||||
$type,
|
||||
$this->attributesFactory->for($reflection),
|
||||
new Properties(...$properties),
|
||||
new Methods(...$methods),
|
||||
new Methods(...$this->methods($reflection, $typeResolver)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReflectionClass<object> $reflection
|
||||
* @return list<MethodDefinition>
|
||||
*/
|
||||
private function methods(ReflectionClass $reflection, ReflectionTypeResolver $typeResolver): array
|
||||
{
|
||||
$methods = [];
|
||||
|
||||
// Because `ReflectionMethod::getMethods()` wont list the constructor if
|
||||
// it comes from a parent class AND is not public, we need to manually
|
||||
// fetch it and add it to the list.
|
||||
if ($reflection->hasMethod('__construct')) {
|
||||
$methods[] = $this->methodBuilder->for($reflection->getMethod('__construct'), $typeResolver);
|
||||
}
|
||||
|
||||
foreach ($reflection->getMethods() as $method) {
|
||||
if ($method->name === '__construct') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$methods[] = $this->methodBuilder->for($method, $typeResolver);
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
private function typeResolver(ClassType $type): ReflectionTypeResolver
|
||||
{
|
||||
$generics = $type->generics();
|
||||
|
@ -150,6 +150,15 @@ final class ReflectionClassDefinitionRepositoryTest extends TestCase
|
||||
self::assertSame('Optional parameter value', $optionalParameter->defaultValue());
|
||||
}
|
||||
|
||||
public function test_private_parent_constructor_is_listed_in_methods(): void
|
||||
{
|
||||
$type = new ClassType(ClassWithInheritedPrivateConstructor::class);
|
||||
$methods = $this->repository->for($type)->methods();
|
||||
|
||||
self::assertTrue($methods->hasConstructor());
|
||||
self::assertFalse($methods->constructor()->isPublic());
|
||||
}
|
||||
|
||||
public function test_invalid_property_type_throws_exception(): void
|
||||
{
|
||||
$class = get_class(new class () {
|
||||
@ -363,3 +372,14 @@ final class ReflectionClassDefinitionRepositoryTest extends TestCase
|
||||
$this->repository->for(new ClassType($class));
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractClassWithPrivateConstructor
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
final class ClassWithInheritedPrivateConstructor extends AbstractClassWithPrivateConstructor
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user