@@ -347,11 +347,14 @@ namespace ts {
347
347
if ( this . declarations ) {
348
348
this . documentationComment = JsDoc . getJsDocCommentsFromDeclarations ( this . declarations ) ;
349
349
350
- if ( this . documentationComment . length === 0 || this . declarations . some ( dec => hasJSDocInheritDocTag ( dec ) ) ) {
350
+ if ( this . documentationComment . length === 0 || this . declarations . some ( hasJSDocInheritDocTag ) ) {
351
351
for ( const declaration of this . declarations ) {
352
352
const inheritedDocs = findInheritedJSDocComments ( declaration , this . getName ( ) , checker ) ;
353
353
if ( inheritedDocs . length > 0 ) {
354
- this . documentationComment = inheritedDocs ;
354
+ if ( this . documentationComment . length > 0 ) {
355
+ inheritedDocs . push ( ts . lineBreakPart ( ) ) ;
356
+ }
357
+ this . documentationComment = concatenate ( inheritedDocs , this . documentationComment ) ;
355
358
break ;
356
359
}
357
360
}
@@ -491,8 +494,15 @@ namespace ts {
491
494
if ( this . declaration ) {
492
495
this . documentationComment = JsDoc . getJsDocCommentsFromDeclarations ( [ this . declaration ] ) ;
493
496
494
- if ( this . documentationComment . length === 0 ) {
495
- this . documentationComment = findInheritedJSDocComments ( this . declaration , this . declaration . symbol . getName ( ) , this . checker ) ;
497
+ if ( this . documentationComment . length === 0 || hasJSDocInheritDocTag ( this . declaration ) ) {
498
+ const inheritedDocs = findInheritedJSDocComments ( this . declaration , this . declaration . symbol . getName ( ) , this . checker ) ;
499
+ if ( this . documentationComment . length > 0 ) {
500
+ inheritedDocs . push ( ts . lineBreakPart ( ) ) ;
501
+ }
502
+ this . documentationComment = concatenate (
503
+ inheritedDocs ,
504
+ this . documentationComment
505
+ ) ;
496
506
}
497
507
}
498
508
else {
@@ -530,51 +540,38 @@ namespace ts {
530
540
* @returns A filled array of documentation comments if any were found, otherwise an empty array.
531
541
*/
532
542
function findInheritedJSDocComments ( declaration : Declaration , propertyName : string , typeChecker : TypeChecker ) : SymbolDisplayPart [ ] {
533
- let documentationComment : SymbolDisplayPart [ ] = [ ] ;
543
+ let foundDocs = false ;
544
+ return flatMap ( getAllSuperTypeNodes ( declaration ) , superTypeNode => {
545
+ if ( foundDocs ) {
546
+ return emptyArray ;
547
+ }
548
+ const superType = typeChecker . getTypeAtLocation ( superTypeNode ) ;
549
+ if ( ! superType ) {
550
+ return emptyArray ;
551
+ }
552
+ const baseProperty = typeChecker . getPropertyOfType ( superType , propertyName ) ;
553
+ if ( ! baseProperty ) {
554
+ return emptyArray ;
555
+ }
556
+ const inheritedDocs = baseProperty . getDocumentationComment ( typeChecker ) ;
557
+ foundDocs = inheritedDocs . length > 0 ;
558
+ return inheritedDocs ;
559
+ } ) ;
560
+ }
534
561
562
+ /**
563
+ * Finds and returns the `TypeNode` for all super classes and implemented interfaces given a declaration.
564
+ * @param declaration The possibly-inherited declaration.
565
+ * @returns A filled array of `TypeNode`s containing all super classes and implemented interfaces if any exist, otherwise an empty array.
566
+ */
567
+ function getAllSuperTypeNodes ( declaration : Declaration ) : ReadonlyArray < TypeNode > {
535
568
const container = declaration . parent ;
536
-
537
569
if ( ! container || ( ! isClassDeclaration ( container ) && ! isInterfaceDeclaration ( container ) ) ) {
538
- return documentationComment ;
539
- }
540
- else {
541
- const baseTypeNode = getClassExtendsHeritageClauseElement ( container ) ;
542
- if ( ! baseTypeNode ) {
543
- return documentationComment ;
544
- }
545
-
546
- const baseType = typeChecker . getTypeAtLocation ( baseTypeNode ) ;
547
- if ( ! baseType ) {
548
- return documentationComment ;
549
- }
550
-
551
- // First check superclasses for a property of the same name
552
- let baseProperty = typeChecker . getPropertyOfType ( baseType , propertyName ) ;
553
- let baseDocs = baseProperty ? baseProperty . getDocumentationComment ( typeChecker ) : [ ] ;
554
- if ( baseDocs . length > 0 ) {
555
- documentationComment = baseDocs ;
556
- }
557
-
558
- // If there's nothing in the superclass, walk through implemented interfaces left-to-right
559
- if ( documentationComment . length === 0 ) {
560
- const implementedInterfaces = map (
561
- getClassImplementsHeritageClauseElements ( container as ClassLikeDeclaration ) ,
562
- interfaceNode => typeChecker . getTypeAtLocation ( interfaceNode )
563
- ) || [ ] ;
564
-
565
- for ( const implementedInterface of implementedInterfaces ) {
566
- // Use the docs from the first implemented interface to have this property and documentation
567
- baseProperty = typeChecker . getPropertyOfType ( implementedInterface , propertyName ) ;
568
- baseDocs = baseProperty ? baseProperty . getDocumentationComment ( typeChecker ) : [ ] ;
569
- if ( baseDocs . length > 0 ) {
570
- documentationComment = baseDocs ;
571
- break ;
572
- }
573
- }
574
- }
575
-
576
- return documentationComment ;
570
+ return emptyArray ;
577
571
}
572
+ const extended = getClassExtendsHeritageClauseElement ( container ) ;
573
+ const types = extended ? [ extended ] : emptyArray ;
574
+ return isClassLike ( container ) ? concatenate ( types , getClassImplementsHeritageClauseElements ( container ) ) : types ;
578
575
}
579
576
580
577
class SourceFileObject extends NodeObject implements SourceFile {
0 commit comments