From 16b32fce7ecfb48bff013a1a2a00365e66957fc7 Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov Date: Sat, 9 Mar 2024 03:35:43 +0300 Subject: [PATCH] Deprecated returning ReflectionClass from ClassLocator::locateClass() (#18) Closes #16 --- CHANGELOG.md | 4 ++ ClassLocator/NativeReflectionFileLocator.php | 1 + ClassLocator/NativeReflectionLocator.php | 1 + TyphoonReflector.php | 60 ++++++++++++++++---- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf6ee4..fd05671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,3 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implemented `getType()`, `getReturnType()`, `getTentativeReturnType()`, `hasTentativeReturnType()`, `hasReturnType()`. - Deprecated `FileResource::changeDetector()`. +- Introduced new parameter `TyphoonReflector::build($fallbackToNativeReflection = true)`. +- Deprecated `NativeReflectionFileLocator`. +- Deprecated `NativeReflectionLocator`. +- Deprecated returning `ReflectionClass` from `ClassLocator::locateClass()`. diff --git a/ClassLocator/NativeReflectionFileLocator.php b/ClassLocator/NativeReflectionFileLocator.php index fe4b57a..8ca3f08 100644 --- a/ClassLocator/NativeReflectionFileLocator.php +++ b/ClassLocator/NativeReflectionFileLocator.php @@ -9,6 +9,7 @@ /** * @api + * @deprecated use TyphoonReflector::build($fallbackToNativeReflection) instead */ final class NativeReflectionFileLocator implements ClassLocator { diff --git a/ClassLocator/NativeReflectionLocator.php b/ClassLocator/NativeReflectionLocator.php index 84f7162..aeb436f 100644 --- a/ClassLocator/NativeReflectionLocator.php +++ b/ClassLocator/NativeReflectionLocator.php @@ -8,6 +8,7 @@ /** * @api + * @deprecated use TyphoonReflector::build($fallbackToNativeReflection) instead */ final class NativeReflectionLocator implements ClassLocator { diff --git a/TyphoonReflector.php b/TyphoonReflector.php index 7adad46..675ee1f 100644 --- a/TyphoonReflector.php +++ b/TyphoonReflector.php @@ -10,8 +10,6 @@ use Typhoon\Reflection\Cache\InMemoryCache; use Typhoon\Reflection\ClassLocator\ClassLocators; use Typhoon\Reflection\ClassLocator\ComposerClassLocator; -use Typhoon\Reflection\ClassLocator\NativeReflectionFileLocator; -use Typhoon\Reflection\ClassLocator\NativeReflectionLocator; use Typhoon\Reflection\ClassLocator\PhpStormStubsClassLocator; use Typhoon\Reflection\ClassReflection\ClassReflector; use Typhoon\Reflection\Exception\ClassDoesNotExist; @@ -36,6 +34,7 @@ private function __construct( private readonly NativeReflector $nativeReflector, private readonly ClassLocator $classLocator, private readonly MetadataStorage $metadataStorage, + private readonly bool $fallbackToNativeReflection, ) {} public static function build( @@ -43,6 +42,7 @@ public static function build( CacheInterface $cache = new InMemoryCache(), TagPrioritizer $tagPrioritizer = new PrefixBasedTagPrioritizer(), ?PhpParser $phpParser = null, + bool $fallbackToNativeReflection = true, ): self { return new self( phpParserReflector: new PhpParserReflector( @@ -52,6 +52,7 @@ public static function build( nativeReflector: new NativeReflector(), classLocator: $classLocator ?? self::defaultClassLocator(), metadataStorage: new MetadataStorage($cache), + fallbackToNativeReflection: $fallbackToNativeReflection, ); } @@ -67,9 +68,6 @@ public static function defaultClassLocator(): ClassLocator $classLocators[] = new ComposerClassLocator(); } - $classLocators[] = new NativeReflectionFileLocator(); - $classLocators[] = new NativeReflectionLocator(); - return new ClassLocators($classLocators); } @@ -139,20 +137,62 @@ private function reflectClassMetadata(string $name): ClassMetadata return $metadata; } - $location = $this->classLocator->locateClass($name) - ?? throw new ClassDoesNotExist($name); + $resource = $this->locateClass($name); - if ($location instanceof \ReflectionClass) { - $metadata = $this->nativeReflector->reflectClass($location); + if ($resource instanceof \ReflectionClass) { + $metadata = $this->nativeReflector->reflectClass($resource); $this->metadataStorage->save($metadata); return $metadata; } - $this->phpParserReflector->reflectFile($location, new WeakClassExistenceChecker($this), $this->metadataStorage); + $this->phpParserReflector->reflectFile($resource, new WeakClassExistenceChecker($this), $this->metadataStorage); $metadata = $this->metadataStorage->get(ClassMetadata::class, $name); $this->metadataStorage->commit(); return $metadata ?? throw new ClassDoesNotExist($name); } + + /** + * @param non-empty-string $name + */ + private function locateClass(string $name): FileResource|\ReflectionClass + { + $resource = $this->classLocator->locateClass($name); + + if ($resource instanceof FileResource) { + return $resource; + } + + if ($resource instanceof \ReflectionClass) { + trigger_deprecation( + 'typhoon/reflection', + '0.3.1', + 'Returning %s from %s is deprecated, use %s::build($fallbackToNativeReflection) instead.', + \ReflectionClass::class, + ClassLocator::class, + self::class, + ); + + return $resource; + } + + if (!$this->fallbackToNativeReflection) { + throw new ClassDoesNotExist($name); + } + + try { + $reflectionClass = new \ReflectionClass($name); + } catch (\ReflectionException) { + throw new ClassDoesNotExist($name); + } + + $file = $reflectionClass->getFileName(); + + if ($file !== false) { + return new FileResource($file, $reflectionClass->getExtensionName()); + } + + return $reflectionClass; + } }