mirror of
https://github.com/danog/Valinor.git
synced 2024-12-02 09:37:46 +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\InvalidTypeAliasImportClass;
|
||||||
use CuyZ\Valinor\Definition\Exception\InvalidTypeAliasImportClassType;
|
use CuyZ\Valinor\Definition\Exception\InvalidTypeAliasImportClassType;
|
||||||
use CuyZ\Valinor\Definition\Exception\UnknownTypeAliasImport;
|
use CuyZ\Valinor\Definition\Exception\UnknownTypeAliasImport;
|
||||||
|
use CuyZ\Valinor\Definition\MethodDefinition;
|
||||||
use CuyZ\Valinor\Definition\Methods;
|
use CuyZ\Valinor\Definition\Methods;
|
||||||
use CuyZ\Valinor\Definition\Properties;
|
use CuyZ\Valinor\Definition\Properties;
|
||||||
use CuyZ\Valinor\Definition\Repository\AttributesRepository;
|
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\ClassType;
|
||||||
use CuyZ\Valinor\Type\Types\UnresolvableType;
|
use CuyZ\Valinor\Type\Types\UnresolvableType;
|
||||||
use CuyZ\Valinor\Utility\Reflection\Reflection;
|
use CuyZ\Valinor\Utility\Reflection\Reflection;
|
||||||
use ReflectionMethod;
|
use ReflectionClass;
|
||||||
use ReflectionProperty;
|
use ReflectionProperty;
|
||||||
|
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
@ -61,19 +62,40 @@ final class ReflectionClassDefinitionRepository implements ClassDefinitionReposi
|
|||||||
$reflection->getProperties()
|
$reflection->getProperties()
|
||||||
);
|
);
|
||||||
|
|
||||||
$methods = array_map(
|
|
||||||
fn (ReflectionMethod $method) => $this->methodBuilder->for($method, $typeResolver),
|
|
||||||
$reflection->getMethods()
|
|
||||||
);
|
|
||||||
|
|
||||||
return new ClassDefinition(
|
return new ClassDefinition(
|
||||||
$type,
|
$type,
|
||||||
$this->attributesFactory->for($reflection),
|
$this->attributesFactory->for($reflection),
|
||||||
new Properties(...$properties),
|
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
|
private function typeResolver(ClassType $type): ReflectionTypeResolver
|
||||||
{
|
{
|
||||||
$generics = $type->generics();
|
$generics = $type->generics();
|
||||||
|
@ -150,6 +150,15 @@ final class ReflectionClassDefinitionRepositoryTest extends TestCase
|
|||||||
self::assertSame('Optional parameter value', $optionalParameter->defaultValue());
|
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
|
public function test_invalid_property_type_throws_exception(): void
|
||||||
{
|
{
|
||||||
$class = get_class(new class () {
|
$class = get_class(new class () {
|
||||||
@ -363,3 +372,14 @@ final class ReflectionClassDefinitionRepositoryTest extends TestCase
|
|||||||
$this->repository->for(new ClassType($class));
|
$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