1212namespace Symfony \Component \PropertyInfo \Extractor ;
1313
1414use phpDocumentor \Reflection \DocBlock ;
15- use phpDocumentor \Reflection \DocBlock \Tags \Factory \StaticMethod ;
16- use phpDocumentor \Reflection \DocBlock \Tags \Generic ;
1715use phpDocumentor \Reflection \DocBlock \Tags \InvalidTag ;
1816use phpDocumentor \Reflection \DocBlockFactory ;
1917use phpDocumentor \Reflection \DocBlockFactoryInterface ;
@@ -42,7 +40,7 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
4240 public const MUTATOR = 2 ;
4341
4442 /**
45- * @var array<string, array{DocBlock|null, int|null, string|null}>
43+ * @var array<string, array{DocBlock|null, int|null, string|null, string|null }>
4644 */
4745 private array $ docBlocks = [];
4846
@@ -70,10 +68,6 @@ public function __construct(?DocBlockFactoryInterface $docBlockFactory = null, ?
7068 throw new \LogicException (\sprintf ('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock". ' , __CLASS__ ));
7169 }
7270
73- if (!is_subclass_of (Generic::class, StaticMethod::class)) {
74- throw new \LogicException ('symfony/property-info v6 does not support phpdocumentor/reflection-docblock v6. Please stick to ^5.2 in your composer.json file. ' );
75- }
76-
7771 $ this ->docBlockFactory = $ docBlockFactory ?: DocBlockFactory::createInstance ();
7872 $ this ->contextFactory = new ContextFactory ();
7973 $ this ->typeContextFactory = new TypeContextFactory ();
@@ -124,7 +118,7 @@ public function getLongDescription(string $class, string $property, array $conte
124118 public function getType (string $ class , string $ property , array $ context = []): ?Type
125119 {
126120 /** @var DocBlock $docBlock */
127- [$ docBlock , $ source , $ prefix ] = $ this ->findDocBlock ($ class , $ property );
121+ [$ docBlock , $ source , $ prefix, $ declaringClass ] = $ this ->findDocBlock ($ class , $ property );
128122 if (!$ docBlock ) {
129123 return null ;
130124 }
@@ -136,7 +130,7 @@ public function getType(string $class, string $property, array $context = []): ?
136130 };
137131
138132 $ types = [];
139- $ typeContext = $ this ->typeContextFactory ->createFromClassName ($ class );
133+ $ typeContext = $ this ->typeContextFactory ->createFromClassName ($ class, $ declaringClass ?? $ class );
140134
141135 /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
142136 foreach ($ docBlock ->getTagsByName ($ tag ) as $ tag ) {
@@ -236,7 +230,7 @@ private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam):
236230 }
237231
238232 /**
239- * @return array{DocBlock|null, int|null, string|null}
233+ * @return array{DocBlock|null, int|null, string|null, string|null }
240234 */
241235 private function findDocBlock (string $ class , string $ property ): array
242236 {
@@ -256,30 +250,35 @@ private function findDocBlock(string $class, string $property): array
256250
257251 switch (true ) {
258252 case $ reflectionProperty ?->isPromoted() && $ docBlock = $ this ->getDocBlockFromConstructor ($ class , $ property ):
259- $ data = [$ docBlock , self ::MUTATOR , null ];
253+ $ data = [$ docBlock , self ::MUTATOR , null , $ reflectionProperty -> getDeclaringClass ()-> getName () ];
260254 break ;
261255
262- case $ docBlock = $ this ->getDocBlockFromProperty ($ class , $ property ):
263- $ data = [$ docBlock , self ::PROPERTY , null ];
256+ case [ $ docBlock, $ declaringClass ] = $ this ->getDocBlockFromProperty ($ class , $ property ):
257+ $ data = [$ docBlock , self ::PROPERTY , null , $ declaringClass ];
264258 break ;
265259
266- case [$ docBlock ] = $ this ->getDocBlockFromMethod ($ class , $ ucFirstProperty , self ::ACCESSOR ):
267- $ data = [$ docBlock , self ::ACCESSOR , null ];
260+ case [$ docBlock, , $ declaringClass ] = $ this ->getDocBlockFromMethod ($ class , $ ucFirstProperty , self ::ACCESSOR ):
261+ $ data = [$ docBlock , self ::ACCESSOR , null , $ declaringClass ];
268262 break ;
269263
270- case [$ docBlock , $ prefix ] = $ this ->getDocBlockFromMethod ($ class , $ ucFirstProperty , self ::MUTATOR ):
271
B72
code>- $ data = [$ docBlock , self ::MUTATOR , $ prefix ];
264+ case [$ docBlock , $ prefix, $ declarin
1004E
gClass ] = $ this ->getDocBlockFromMethod ($ class , $ ucFirstProperty , self ::MUTATOR ):
265+ $ data = [$ docBlock , self ::MUTATOR , $ prefix, $ declaringClass ];
272266 break ;
273267
274268 default :
275- $ data = [null , null , null ];
269+ $ data = [null , null , null , null ];
276270 }
277271
278272 return $ this ->docBlocks [$ propertyHash ] = $ data ;
279273 }
280274
281- private function getDocBlockFromProperty (string $ class , string $ property ): ?DocBlock
275+ /**
276+ * @return array{DocBlock, string}|null
277+ */
278+ private function getDocBlockFromProperty (string $ class , string $ property , ?string $ originalClass = null ): ?array
282279 {
280+ $ originalClass ??= $ class ;
281+
283282 // Use a ReflectionProperty instead of $class to get the parent class if applicable
284283 try {
285284 $ reflectionProperty = new \ReflectionProperty ($ class , $ property );
@@ -291,22 +290,25 @@ private function getDocBlockFromProperty(string $class, string $property): ?DocB
291290
292291 foreach ($ reflector ->getTraits () as $ trait ) {
293292 if ($ trait ->hasProperty ($ property )) {
294- return $ this ->getDocBlockFromProperty ($ trait ->getName (), $ property );
293+ return $ this ->getDocBlockFromProperty ($ trait ->getName (), $ property, $ reflector -> isTrait () ? $ originalClass : $ reflector -> getName () );
295294 }
296295 }
297296
298297 try {
299- return $ this ->docBlockFactory ->create ($ reflectionProperty , $ this ->createFromReflector ($ reflector ));
298+ $ declaringClass = $ reflector ->isTrait () ? $ originalClass : $ reflector ->getName ();
299+
300+ return [$ this ->docBlockFactory ->create ($ reflectionProperty , $ this ->createFromReflector ($ reflector )), $ declaringClass ];
300301 } catch (\InvalidArgumentException |\RuntimeException ) {
301302 return null ;
302303 }
303304 }
304305
305306 /**
306- * @return array{DocBlock, string}|null
307+ * @return array{DocBlock, string, string }|null
307308 */
308- private function getDocBlockFromMethod (string $ class , string $ ucFirstProperty , int $ type ): ?array
309+ private function getDocBlockFromMethod (string $ class , string $ ucFirstProperty , int $ type, ? string $ originalClass = null ): ?array
309310 {
311+ $ originalClass ??= $ class ;
310312 $ prefixes = self ::ACCESSOR === $ type ? $ this ->accessorPrefixes : $ this ->mutatorPrefixes ;
311313 $ prefix = null ;
312314 $ method = null ;
@@ -343,12 +345,14 @@ private function getDocBlockFromMethod(string $class, string $ucFirstProperty, i
343345
344346 foreach ($ reflector ->getTraits () as $ trait ) {
345347 if ($ trait ->hasMethod ($ methodName )) {
346- return $ this ->getDocBlockFromMethod ($ trait ->getName (), $ ucFirstProperty , $ type );
348+ return $ this ->getDocBlockFromMethod ($ trait ->getName (), $ ucFirstProperty , $ type, $ reflector -> isTrait () ? $ originalClass : $ reflector -> getName () );
347349 }
348350 }
349351
350352 try {
351- return [$ this ->docBlockFactory ->create ($ method , $ this ->createFromReflector ($ reflector )), $ prefix ];
353+ $ declaringClass = $ reflector ->isTrait () ? $ originalClass : $ reflector ->getName ();
354+
355+ return [$ this ->docBlockFactory ->create ($ method , $ this ->createFromReflector ($ reflector )), $ prefix , $ declaringClass ];
352356 } catch (\InvalidArgumentException |\RuntimeException ) {
353357 return null ;
354358 }
0 commit comments