Skip to content

Commit

Permalink
misc: separate native type and docblock type for property and parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Mar 17, 2024
1 parent ba67703 commit 37993b6
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/Definition/ParameterDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function __construct(
/** @var non-empty-string */
public readonly string $signature,
public readonly Type $type,
public readonly Type $nativeType,
public readonly bool $isOptional,
public readonly bool $isVariadic,
public readonly mixed $defaultValue,
Expand Down
1 change: 1 addition & 0 deletions src/Definition/PropertyDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function __construct(
/** @var non-empty-string */
public readonly string $signature,
public readonly Type $type,
public readonly Type $nativeType,
public readonly bool $hasDefaultValue,
public readonly mixed $defaultValue,
public readonly bool $isPublic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ public function compile(ParameterDefinition $parameter): string
$isVariadic = var_export($parameter->isVariadic, true);
$defaultValue = $this->defaultValue($parameter);
$type = $this->typeCompiler->compile($parameter->type);
$nativeType = $this->typeCompiler->compile($parameter->nativeType);
$attributes = $this->attributesCompiler->compile($parameter->attributes);

return <<<PHP
new \CuyZ\Valinor\Definition\ParameterDefinition(
'{$parameter->name}',
'{$parameter->signature}',
$type,
$nativeType,
$isOptional,
$isVariadic,
$defaultValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function __construct(
public function compile(PropertyDefinition $property): string
{
$type = $this->typeCompiler->compile($property->type);
$nativeType = $this->typeCompiler->compile($property->nativeType);
$hasDefaultValue = var_export($property->hasDefaultValue, true);
$defaultValue = var_export($property->defaultValue, true);
$isPublic = var_export($property->isPublic, true);
Expand All @@ -27,6 +28,7 @@ public function compile(PropertyDefinition $property): string
'{$property->name}',
'{$property->signature}',
$type,
$nativeType,
$hasDefaultValue,
$defaultValue,
$isPublic,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function for(ReflectionParameter $reflection, ReflectionTypeResolver $typ
$name = $reflection->name;
$signature = Reflection::signature($reflection);
$type = $typeResolver->resolveType($reflection);
$nativeType = $typeResolver->resolveNativeType($reflection);
$isOptional = $reflection->isOptional();
$isVariadic = $reflection->isVariadic();

Expand All @@ -48,6 +49,7 @@ public function for(ReflectionParameter $reflection, ReflectionTypeResolver $typ
$name,
$signature,
$type,
$nativeType,
$isOptional,
$isVariadic,
$defaultValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function for(ReflectionProperty $reflection, ReflectionTypeResolver $type
$name = $reflection->name;
$signature = Reflection::signature($reflection);
$type = $typeResolver->resolveType($reflection);
$nativeType = $typeResolver->resolveNativeType($reflection);
$hasDefaultValue = $this->hasDefaultValue($reflection, $type);
$defaultValue = $reflection->getDefaultValue();
$isPublic = $reflection->isPublic();
Expand All @@ -43,6 +44,7 @@ public function for(ReflectionProperty $reflection, ReflectionTypeResolver $type
$name,
$signature,
$type,
$nativeType,
$hasDefaultValue,
$defaultValue,
$isPublic,
Expand Down
56 changes: 25 additions & 31 deletions src/Definition/Repository/Reflection/ReflectionTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,21 @@
use ReflectionParameter;
use ReflectionProperty;

use function trim;

/** @internal */
final class ReflectionTypeResolver
{
public function __construct(
private TypeParser $nativeParser,
private TypeParser $advancedParser
private TypeParser $advancedParser,
) {}

public function resolveType(ReflectionProperty|ReflectionParameter|ReflectionFunctionAbstract $reflection): Type
{
$nativeType = $this->nativeType($reflection);
$nativeType = $this->resolveNativeType($reflection);
$typeFromDocBlock = $this->typeFromDocBlock($reflection);

if (! $nativeType && ! $typeFromDocBlock) {
return MixedType::get();
}

if (! $nativeType) {
/** @var Type $typeFromDocBlock */
return $typeFromDocBlock;
}

if (! $typeFromDocBlock) {
// When the type is a class, it may declare templates that must be
// filled with generics. PHP does not handle generics natively, so
Expand All @@ -53,16 +46,33 @@ public function resolveType(ReflectionProperty|ReflectionParameter|ReflectionFun
return $nativeType;
}

if (! $typeFromDocBlock instanceof UnresolvableType
&& ! $nativeType instanceof UnresolvableType
&& ! $typeFromDocBlock->matches($nativeType)
) {
if ($typeFromDocBlock instanceof UnresolvableType) {
return $typeFromDocBlock;
}

if (! $typeFromDocBlock->matches($nativeType)) {
throw new TypesDoNotMatch($reflection, $typeFromDocBlock, $nativeType);
}

return $typeFromDocBlock;
}

public function resolveNativeType(ReflectionProperty|ReflectionParameter|ReflectionFunctionAbstract $reflection): Type
{
$reflectionType = $reflection instanceof ReflectionFunctionAbstract
? $reflection->getReturnType()
: $reflection->getType();

if (! $reflectionType) {
return MixedType::get();
}

$type = Reflection::flattenType($reflectionType);
$type = $this->parseType($type, $reflection, $this->nativeParser);

return $this->handleVariadicType($reflection, $type);
}

private function typeFromDocBlock(ReflectionProperty|ReflectionParameter|ReflectionFunctionAbstract $reflection): ?Type
{
if ($reflection instanceof ReflectionFunctionAbstract) {
Expand Down Expand Up @@ -91,22 +101,6 @@ private function typeFromDocBlock(ReflectionProperty|ReflectionParameter|Reflect
return $this->handleVariadicType($reflection, $type);
}

private function nativeType(ReflectionProperty|ReflectionParameter|ReflectionFunctionAbstract $reflection): ?Type
{
$reflectionType = $reflection instanceof ReflectionFunctionAbstract
? $reflection->getReturnType()
: $reflection->getType();

if (! $reflectionType) {
return null;
}

$type = Reflection::flattenType($reflectionType);
$type = $this->parseType($type, $reflection, $this->nativeParser);

return $this->handleVariadicType($reflection, $type);
}

private function parseType(string $raw, ReflectionProperty|ReflectionParameter|ReflectionFunctionAbstract $reflection, TypeParser $parser): Type
{
try {
Expand Down
1 change: 1 addition & 0 deletions tests/Fake/Definition/FakeFunctionDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static function new(string $fileName = null): FunctionDefinition
'bar',
'foo::bar',
NativeStringType::get(),
NativeStringType::get(),
false,
false,
'foo',
Expand Down
3 changes: 3 additions & 0 deletions tests/Fake/Definition/FakeParameterDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static function new(string $name = 'someParameter', Type $type = null): P
$name,
$name,
$type ?? new FakeType(),
$type ?? new FakeType(),
false,
false,
null,
Expand All @@ -39,6 +40,7 @@ public static function optional(string $name, Type $type, mixed $defaultValue):
$name,
$name,
$type,
$type,
true,
false,
$defaultValue,
Expand All @@ -60,6 +62,7 @@ public static function fromReflection(ReflectionParameter $reflection): Paramete
$name,
'Signature::' . $reflection->name,
$type,
$type,
$reflection->isOptional(),
$reflection->isVariadic(),
$reflection->isDefaultValueAvailable() ? $reflection->getDefaultValue() : null,
Expand Down
2 changes: 2 additions & 0 deletions tests/Fake/Definition/FakePropertyDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static function new(string $name = 'someProperty'): PropertyDefinition
$name,
$name,
new MixedType(),
new MixedType(),
false,
null,
false,
Expand All @@ -45,6 +46,7 @@ public static function fromReflection(ReflectionProperty $reflection): PropertyD
$name,
'Signature::' . $reflection->name,
$type,
new MixedType(),
isset($defaultProperties[$reflection->name]),
$defaultProperties[$reflection->name] ?? null,
$reflection->isPublic(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function test_function_is_compiled_correctly(): void
'bar',
'foo::bar',
NativeStringType::get(),
NativeStringType::get(),
false,
false,
'foo',
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/Definition/ParameterDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public function test_parameter_data_can_be_retrieved(): void
$name,
$signature,
$type,
$type,
$isOptional,
$isVariadic,
$defaultValue,
Expand Down
3 changes: 3 additions & 0 deletions tests/Unit/Definition/PropertyDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function test_property_data_can_be_retrieved(): void
$name = 'someProperty';
$signature = 'somePropertySignature';
$type = new FakeType();
$nativeType = new FakeType();
$hasDefaultValue = true;
$defaultValue = 'Some property default value';
$isPublic = true;
Expand All @@ -25,6 +26,7 @@ public function test_property_data_can_be_retrieved(): void
$name,
$signature,
$type,
$nativeType,
$hasDefaultValue,
$defaultValue,
$isPublic,
Expand All @@ -34,6 +36,7 @@ public function test_property_data_can_be_retrieved(): void
self::assertSame($name, $property->name);
self::assertSame($signature, $property->signature);
self::assertSame($type, $property->type);
self::assertSame($nativeType, $property->nativeType);
self::assertSame($hasDefaultValue, $property->hasDefaultValue);
self::assertSame($defaultValue, $property->defaultValue);
self::assertSame($isPublic, $property->isPublic);
Expand Down

0 comments on commit 37993b6

Please sign in to comment.