1313
1414use phpDocumentor \Reflection \DocBlock ;
1515use phpDocumentor \Reflection \DocBlock \Tag ;
16+ use phpDocumentor \Reflection \Fqsen ;
17+ use phpDocumentor \Reflection \Php \Class_ ;
1618use phpDocumentor \Reflection \Php \File ;
19+ use phpDocumentor \Reflection \Php \Interface_ ;
1720use phpDocumentor \Reflection \Php \Project ;
1821use phpDocumentor \Reflection \Types \Compound ;
1922use phpDocumentor \Reflection \Types \Null_ ;
@@ -252,17 +255,102 @@ private function getDocBlock(Project $project, int $objectType, string $namespac
252255 }
253256
254257 $ fqsen = $ namespace .'\\' .$ object ;
255- $ function = sprintf ('%s::%s() ' , $ fqsen , $ function );
258+ $ fqfunction = sprintf ('%s::%s() ' , $ fqsen , $ function );
256259
257260 foreach ($ project ->getFiles () as $ file ) {
258261 foreach ($ file ->$ method () as $ obj ) {
259262 if ($ obj ->getFqsen ()->__toString () === $ fqsen ) {
260- return $ this ->getDocBlockForFunction ($ obj ->getMethods (), $ function );
263+ $ docBlock = $ this ->getDocBlockForFunction ($ obj ->getMethods (), $ fqfunction );
264+
265+ if (
266+ self ::OBJECT_TRAIT === $ objectType ||
267+ (null !== $ docBlock && 0 !== strcasecmp ('{@inheritdoc} ' , trim ($ docBlock ->getSummary ())))
268+ ) {
269+ return $ docBlock ;
270+ }
271+
272+ if ($ obj instanceof Class_) {
273+ if ($ docBlock = $ this ->getDocBlockForInterfaces ($ project , $ obj ->getInterfaces (), $ function )) {
274+ return $ docBlock ;
275+ }
276+
277+ $ parentFqsen = $ obj ->getParent ();
278+ if (!$ parent = $ this ->getObject ($ project , $ parentFqsen , self ::OBJECT_CLASS )) {
279+ return ;
280+ }
281+
282+ return $ this ->getDocBlock ($ project , self ::OBJECT_CLASS , $ this ->getNamespace ($ parentFqsen ), $ parent ->getName (), $ function );
283+ }
284+
285+ if ($ obj instanceof Interface_ && $ docBlock = $ this ->getDocBlockForInterfaces ($ project , $ obj ->getParents (), $ function )) {
286+ return $ docBlock ;
287+ }
261288 }
262289 }
263290 }
264291 }
265292
293+ /**
294+ * Extracts a namespace from a FQSEN.
295+ *
296+ * @param Fqsen $fqsen
297+ *
298+ * @return string
299+ */
300+ private function getNamespace (Fqsen $ fqsen ): string
301+ {
302+ $ value = $ fqsen ->__toString ();
303+ return substr ($ value , 0 , strrpos ($ value , '\\' ));
304+ }
305+
306+ /**
307+ * Finds a Class_ or an Interface_ instance using its FQSEN.
308+ *
309+ * @param Project $project
310+ * @param Fqsen $fqsen
311+ * @param int $objectType
312+ *
313+ * @return Class_|Interface_|null
314+ */
315+ private function getObject (Project $ project , Fqsen $ fqsen , int $ objectType )
316+ {
317+ $ method = self ::OBJECT_CLASS === $ objectType ? 'getClasses ' : 'getInterfaces ' ;
318+
319+ foreach ($ project ->getFiles () as $ file ) {
320+ foreach ($ file ->$ method () as $ object ) {
321+ if ($ object ->getFqsen ()->__toString () === $ fqsen ->__toString ()) {
322+ return $ object ;
323+ }
324+ }
325+ }
326+ }
327+
328+ /**
329+ * Gets a DocBlock from an array of interfaces FQSEN instances.
330+ *
331+ * @param Project $project
332+ * @param Fqsen[] $fqsens
333+ * @param string $function
334+ *
335+ * @return DocBlock|null
336+ */
337+ private function getDocBlockForInterfaces (Project $ project , array $ fqsens , string $ function )
338+ {
339+ foreach ($ fqsens as $ fqsen ) {
340+ $ object = $ this ->getObject ($ project , $ fqsen , self ::OBJECT_INTERFACE );
341+
342+ if (!$ object ) {
343+ continue ;
344+ }
345+
346+ $ docBlock = $ this ->getDocBlock ($ project , self ::OBJECT_INTERFACE , $ this ->getNamespace ($ fqsen ), $ object ->getName (), $ function );
347+
348+ if ($ docBlock ) {
349+ return $ docBlock ;
350+ }
351+ }
352+ }
353+
266354 /**
267355 * Gets the DocBlock of a function.
268356 *
@@ -278,17 +366,7 @@ private function getDocBlockForFunction(array $functions, string $function)
278366 continue ;
279367 }
280368
281- // TODO: handle inheritance
282-
283- if (!$ docBlock = $ reflectionFunction ->getDocblock ()) {
284- return ;
285- }
286-
287- // TODO: handle {@inheritdoc}
288-
289- // TODO: cache this for performance
290-
291- return $ docBlock ;
369+ return $ reflectionFunction ->getDocblock ();
292370 }
293371 }
294372
0 commit comments