1010use Typhoon \Reflection \Cache \InMemoryCache ;
1111use Typhoon \Reflection \ClassLocator \ClassLocators ;
1212use Typhoon \Reflection \ClassLocator \ComposerClassLocator ;
13- use Typhoon \Reflection \ClassLocator \NativeReflectionFileLocator ;
14- use Typhoon \Reflection \ClassLocator \NativeReflectionLocator ;
1513use Typhoon \Reflection \ClassLocator \PhpStormStubsClassLocator ;
1614use Typhoon \Reflection \ClassReflection \ClassReflector ;
1715use Typhoon \Reflection \Exception \ClassDoesNotExist ;
@@ -36,13 +34,15 @@ private function __construct(
3634 private readonly NativeReflector $ nativeReflector ,
3735 private readonly ClassLocator $ classLocator ,
3836 private readonly MetadataStorage $ metadataStorage ,
37+ private readonly bool $ fallbackToNativeReflection ,
3938 ) {}
4039
4140 public static function build (
4241 ?ClassLocator $ classLocator = null ,
4342 CacheInterface $ cache = new InMemoryCache (),
4443 TagPrioritizer $ tagPrioritizer = new PrefixBasedTagPrioritizer (),
4544 ?PhpParser $ phpParser = null ,
45+ bool $ fallbackToNativeReflection = true ,
4646 ): self {
4747 return new self (
4848 phpParserReflector: new PhpParserReflector (
@@ -52,6 +52,7 @@ public static function build(
5252 nativeReflector: new NativeReflector (),
5353 classLocator: $ classLocator ?? self ::defaultClassLocator (),
5454 metadataStorage: new MetadataStorage ($ cache ),
55+ fallbackToNativeReflection: $ fallbackToNativeReflection ,
5556 );
5657 }
5758
@@ -67,9 +68,6 @@ public static function defaultClassLocator(): ClassLocator
6768 $ classLocators [] = new ComposerClassLocator ();
6869 }
6970
70- $ classLocators [] = new NativeReflectionFileLocator ();
71- $ classLocators [] = new NativeReflectionLocator ();
72-
7371 return new ClassLocators ($ classLocators );
7472 }
7573
@@ -139,20 +137,62 @@ private function reflectClassMetadata(string $name): ClassMetadata
139137 return $ metadata ;
140138 }
141139
142- $ location = $ this ->classLocator ->locateClass ($ name )
143- ?? throw new ClassDoesNotExist ($ name );
140+ $ resource = $ this ->locateClass ($ name );
144141
145- if ($ location instanceof \ReflectionClass) {
146- $ metadata = $ this ->nativeReflector ->reflectClass ($ location );
142+ if ($ resource instanceof \ReflectionClass) {
143+ $ metadata = $ this ->nativeReflector ->reflectClass ($ resource );
147144 $ this ->metadataStorage ->save ($ metadata );
148145
149146 return $ metadata ;
150147 }
151148
152- $ this ->phpParserReflector ->reflectFile ($ location , new WeakClassExistenceChecker ($ this ), $ this ->metadataStorage );
149+ $ this ->phpParserReflector ->reflectFile ($ resource , new WeakClassExistenceChecker ($ this ), $ this ->metadataStorage );
153150 $ metadata = $ this ->metadataStorage ->get (ClassMetadata::class, $ name );
154151 $ this ->metadataStorage ->commit ();
155152
156153 return $ metadata ?? throw new ClassDoesNotExist ($ name );
157154 }
155+
156+ /**
157+ * @param non-empty-string $name
158+ */
159+ private function locateClass (string $ name ): FileResource |\ReflectionClass
160+ {
161+ $ resource = $ this ->classLocator ->locateClass ($ name );
162+
163+ if ($ resource instanceof FileResource) {
164+ return $ resource ;
165+ }
166+
167+ if ($ resource instanceof \ReflectionClass) {
168+ trigger_deprecation (
169+ 'typhoon/reflection ' ,
170+ '0.3.1 ' ,
171+ 'Returning %s from %s is deprecated, use %s::build($fallbackToNativeReflection) instead. ' ,
172+ \ReflectionClass::class,
173+ ClassLocator::class,
174+ self ::class,
175+ );
176+
177+ return $ resource ;
178+ }
179+
180+ if (!$ this ->fallbackToNativeReflection ) {
181+ throw new ClassDoesNotExist ($ name );
182+ }
183+
184+ try {
185+ $ reflectionClass = new \ReflectionClass ($ name );
186+ } catch (\ReflectionException ) {
187+ throw new ClassDoesNotExist ($ name );
188+ }
189+
190+ $ file = $ reflectionClass ->getFileName ();
191+
192+ if ($ file !== false ) {
193+ return new FileResource ($ file , $ reflectionClass ->getExtensionName ());
194+ }
195+
196+ return $ reflectionClass ;
197+ }
158198}
0 commit comments