From e2451df2c1857a935a1fc2e88c056d6b414ed924 Mon Sep 17 00:00:00 2001 From: Romain Canon Date: Thu, 17 Mar 2022 21:38:46 +0100 Subject: [PATCH] misc: handle class name in function definition --- src/Definition/FunctionDefinition.php | 24 +++++++++++++++++-- .../Compiler/FunctionDefinitionCompiler.php | 4 ++++ ...ReflectionFunctionDefinitionRepository.php | 19 +++++++++++++-- .../Definition/FakeFunctionDefinition.php | 2 ++ .../FunctionDefinitionCompilerTest.php | 3 +++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/Definition/FunctionDefinition.php b/src/Definition/FunctionDefinition.php index a4356c7..a9f45b7 100644 --- a/src/Definition/FunctionDefinition.php +++ b/src/Definition/FunctionDefinition.php @@ -17,10 +17,22 @@ final class FunctionDefinition private Type $returnType; - public function __construct(string $name, string $signature, Parameters $parameters, Type $returnType) - { + /** @var class-string|null */ + private ?string $class; + + /** + * @param class-string|null $class + */ + public function __construct( + string $name, + string $signature, + ?string $class, + Parameters $parameters, + Type $returnType + ) { $this->name = $name; $this->signature = $signature; + $this->class = $class; $this->parameters = $parameters; $this->returnType = $returnType; } @@ -35,6 +47,14 @@ final class FunctionDefinition return $this->signature; } + /** + * @return class-string|null + */ + public function class(): ?string + { + return $this->class; + } + /** * @phpstan-return Parameters * @return Parameters&ParameterDefinition[] diff --git a/src/Definition/Repository/Cache/Compiler/FunctionDefinitionCompiler.php b/src/Definition/Repository/Cache/Compiler/FunctionDefinitionCompiler.php index bbde190..40ee414 100644 --- a/src/Definition/Repository/Cache/Compiler/FunctionDefinitionCompiler.php +++ b/src/Definition/Repository/Cache/Compiler/FunctionDefinitionCompiler.php @@ -8,6 +8,8 @@ use CuyZ\Valinor\Cache\Compiled\CacheCompiler; use CuyZ\Valinor\Definition\FunctionDefinition; use CuyZ\Valinor\Definition\ParameterDefinition; +use function var_export; + /** @internal */ final class FunctionDefinitionCompiler implements CacheCompiler { @@ -30,6 +32,7 @@ final class FunctionDefinitionCompiler implements CacheCompiler iterator_to_array($value->parameters()) ); + $class = var_export($value->class(), true); $parameters = implode(', ', $parameters); $returnType = $this->typeCompiler->compile($value->returnType()); @@ -37,6 +40,7 @@ final class FunctionDefinitionCompiler implements CacheCompiler new \CuyZ\Valinor\Definition\FunctionDefinition( '{$value->name()}', '{$value->signature()}', + $class, new \CuyZ\Valinor\Definition\Parameters($parameters), $returnType ) diff --git a/src/Definition/Repository/Reflection/ReflectionFunctionDefinitionRepository.php b/src/Definition/Repository/Reflection/ReflectionFunctionDefinitionRepository.php index db366e5..e1c7df7 100644 --- a/src/Definition/Repository/Reflection/ReflectionFunctionDefinitionRepository.php +++ b/src/Definition/Repository/Reflection/ReflectionFunctionDefinitionRepository.php @@ -9,6 +9,8 @@ use CuyZ\Valinor\Definition\Parameters; use CuyZ\Valinor\Definition\Repository\AttributesRepository; use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository; use CuyZ\Valinor\Type\Parser\Factory\Specifications\AliasSpecification; +use CuyZ\Valinor\Type\Parser\Factory\Specifications\ClassContextSpecification; +use CuyZ\Valinor\Type\Parser\Factory\Specifications\HandleClassGenericSpecification; use CuyZ\Valinor\Type\Parser\Factory\TypeParserFactory; use CuyZ\Valinor\Utility\Reflection\Reflection; use ReflectionFunction; @@ -43,6 +45,8 @@ final class ReflectionFunctionDefinitionRepository implements FunctionDefinition return new FunctionDefinition( $reflection->getName(), Reflection::signature($reflection), + // @PHP 8.0 nullsafe operator + $reflection->getClosureScopeClass() ? $reflection->getClosureScopeClass()->name : null, new Parameters(...$parameters), $returnType ); @@ -50,8 +54,19 @@ final class ReflectionFunctionDefinitionRepository implements FunctionDefinition private function typeResolver(ReflectionFunction $reflection): ReflectionTypeResolver { - $advancedParser = $this->typeParserFactory->get(new AliasSpecification($reflection)); - $nativeParser = $this->typeParserFactory->get(); + $class = $reflection->getClosureScopeClass(); + + $nativeSpecifications = []; + $advancedSpecification = [new AliasSpecification($reflection)]; + + if ($class !== null) { + $nativeSpecifications[] = new ClassContextSpecification($class->name); + $advancedSpecification[] = new ClassContextSpecification($class->name); + $advancedSpecification[] = new HandleClassGenericSpecification(); + } + + $nativeParser = $this->typeParserFactory->get(...$nativeSpecifications); + $advancedParser = $this->typeParserFactory->get(...$advancedSpecification); return new ReflectionTypeResolver($nativeParser, $advancedParser); } diff --git a/tests/Fake/Definition/FakeFunctionDefinition.php b/tests/Fake/Definition/FakeFunctionDefinition.php index 9740f7f..6766fb6 100644 --- a/tests/Fake/Definition/FakeFunctionDefinition.php +++ b/tests/Fake/Definition/FakeFunctionDefinition.php @@ -9,6 +9,7 @@ use CuyZ\Valinor\Definition\FunctionDefinition; use CuyZ\Valinor\Definition\ParameterDefinition; use CuyZ\Valinor\Definition\Parameters; use CuyZ\Valinor\Type\Types\NativeStringType; +use stdClass; final class FakeFunctionDefinition { @@ -17,6 +18,7 @@ final class FakeFunctionDefinition return new FunctionDefinition( 'foo', 'foo:42-1337', + stdClass::class, new Parameters( new ParameterDefinition( 'bar', diff --git a/tests/Functional/Definition/Repository/Cache/Compiler/FunctionDefinitionCompilerTest.php b/tests/Functional/Definition/Repository/Cache/Compiler/FunctionDefinitionCompilerTest.php index 24c5a58..c15fb72 100644 --- a/tests/Functional/Definition/Repository/Cache/Compiler/FunctionDefinitionCompilerTest.php +++ b/tests/Functional/Definition/Repository/Cache/Compiler/FunctionDefinitionCompilerTest.php @@ -12,6 +12,7 @@ use CuyZ\Valinor\Definition\Repository\Cache\Compiler\FunctionDefinitionCompiler use CuyZ\Valinor\Type\Types\NativeStringType; use Error; use PHPUnit\Framework\TestCase; +use stdClass; final class FunctionDefinitionCompilerTest extends TestCase { @@ -29,6 +30,7 @@ final class FunctionDefinitionCompilerTest extends TestCase $function = new FunctionDefinition( 'foo', 'foo:42-1337', + stdClass::class, new Parameters( new ParameterDefinition( 'bar', @@ -48,6 +50,7 @@ final class FunctionDefinitionCompilerTest extends TestCase self::assertSame('foo', $compiledFunction->name()); self::assertSame('foo:42-1337', $compiledFunction->signature()); + self::assertSame(stdClass::class, $compiledFunction->class()); self::assertTrue($compiledFunction->parameters()->has('bar')); self::assertInstanceOf(NativeStringType::class, $compiledFunction->returnType()); }