@@ -233,7 +233,8 @@ class SphinxDocsGenerator extends Generator {
233
233
this . namespaceStack . push ( { name : className , underClass : true } ) ;
234
234
}
235
235
236
- protected onEndClass ( _cls : spec . ClassType ) {
236
+ protected onEndClass ( cls : spec . ClassType ) {
237
+ this . renderInheritedMembers ( cls ) ;
237
238
this . code . closeBlock ( ) ;
238
239
this . namespaceStack . pop ( ) ;
239
240
if ( ! this . topNamespace . underClass ) { this . closeSection ( ) ; }
@@ -342,7 +343,8 @@ class SphinxDocsGenerator extends Generator {
342
343
this . code . line ( ) ;
343
344
}
344
345
345
- protected onEndInterface ( _ifc : spec . InterfaceType ) {
346
+ protected onEndInterface ( ifc : spec . InterfaceType ) {
347
+ this . renderInheritedMembers ( ifc ) ;
346
348
this . code . closeBlock ( ) ;
347
349
if ( ! this . topNamespace . underClass ) { this . closeSection ( ) ; }
348
350
}
@@ -359,6 +361,62 @@ class SphinxDocsGenerator extends Generator {
359
361
this . renderProperty ( property ) ;
360
362
}
361
363
364
+ private renderInheritedMembers ( entity : spec . ClassType | spec . InterfaceType ) {
365
+ const inherited = this . getInheritedMembers ( entity ) ;
366
+ if ( Object . keys ( inherited ) . length === 0 ) { return ; }
367
+ for ( const source of Object . keys ( inherited ) . sort ( ) ) {
368
+ const entities = inherited [ source ] ;
369
+ for ( const method of entities . methods ) {
370
+ this . renderMethod ( method , source ) ;
371
+ for ( const overload of this . createOverloadsForOptionals ( method ) ) {
372
+ this . renderMethod ( overload , source ) ;
373
+ }
374
+ }
375
+ for ( const property of entities . properties ) {
376
+ this . renderProperty ( property , source ) ;
377
+ }
378
+ }
379
+ }
380
+
381
+ private getInheritedMembers ( entity : spec . ClassType | spec . InterfaceType ) : InheritedMembers {
382
+ const parents = parentTypes ( entity ) ;
383
+ const knownMembers = new Set < string > ( [
384
+ ...( entity . methods || [ ] ) . map ( m => m . name ! ) ,
385
+ ...( entity . properties || [ ] ) . map ( p => p . name )
386
+ ] ) ;
387
+ const result : InheritedMembers = { } ;
388
+ for ( const parent of parents ) {
389
+ const parentType = this . findType ( parent . fqn ) as spec . ClassType | spec . InterfaceType ;
390
+ for ( const method of parentType . methods || [ ] ) {
391
+ if ( method . static || knownMembers . has ( method . name ! ) ) { continue ; }
392
+ result [ parentType . fqn ] = result [ parentType . fqn ] || { methods : [ ] , properties : [ ] } ;
393
+ result [ parentType . fqn ] . methods . push ( method ) ;
394
+ knownMembers . add ( method . name ! ) ;
395
+ }
396
+ for ( const property of parentType . properties || [ ] ) {
397
+ if ( property . static || knownMembers . has ( property . name ! ) ) { continue ; }
398
+ result [ parentType . fqn ] = result [ parentType . fqn ] || { methods : [ ] , properties : [ ] } ;
399
+ result [ parentType . fqn ] . properties . push ( property ) ;
400
+ knownMembers . add ( property . name ) ;
401
+ }
402
+ for ( const superType of parentTypes ( parentType ) ) {
403
+ parents . push ( superType ) ;
404
+ }
405
+ }
406
+ return result ;
407
+
408
+ function parentTypes ( type : spec . ClassType | spec . InterfaceType ) {
409
+ const types = new Array < spec . NamedTypeReference > ( ) ;
410
+ if ( spec . isClassType ( type ) && type . base ) {
411
+ types . push ( type . base ) ;
412
+ }
413
+ if ( type . interfaces ) {
414
+ types . push ( ...type . interfaces ) ;
415
+ }
416
+ return types ;
417
+ }
418
+ }
419
+
362
420
/**
363
421
* Adds a title to the current code file, using the appropriate header
364
422
* adornment given the current TOC depth. It will start using simple
@@ -402,7 +460,7 @@ class SphinxDocsGenerator extends Generator {
402
460
signature += ', ' ;
403
461
}
404
462
405
- if ( p . type . optional ) {
463
+ if ( p . type . optional && ! params . slice ( idx + 1 ) . find ( e => ! e . type . optional ) ) {
406
464
signature += '[' ;
407
465
signaturePosfix += ']' ;
408
466
}
@@ -437,22 +495,40 @@ class SphinxDocsGenerator extends Generator {
437
495
}
438
496
}
439
497
440
- private renderMethod ( method : spec . Method ) {
498
+ private renderMethod ( method : spec . Method , inheritedFrom ?: string ) {
441
499
const signature = this . renderMethodSignature ( method ) ;
442
500
443
501
const type = method . static ? `py:staticmethod` : `py:method` ;
444
502
445
503
this . code . line ( ) ;
446
504
this . code . openBlock ( `.. ${ type } :: ${ method . name } ${ signature } ` ) ;
447
505
506
+ if ( inheritedFrom ) {
507
+ this . code . line ( ) ;
508
+ this . code . line ( `*Inherited from* :py:meth:\`${ inheritedFrom } <${ inheritedFrom } .${ method . name } >\`` ) ;
509
+ } else if ( method . overrides ) {
510
+ this . code . line ( ) ;
511
+ const superType = this . findType ( method . overrides . fqn ) as spec . ClassType | spec . InterfaceType ;
512
+ if ( spec . isInterfaceType ( superType ) || superType . methods ! . find ( m => m . name === method . name && ! ! m . abstract ) ) {
513
+ this . code . line ( `*Implements* :py:meth:\`${ method . overrides . fqn } .${ method . name } \`` ) ;
514
+ } else {
515
+ this . code . line ( `*Overrides* :py:meth:\`${ method . overrides . fqn } .${ method . name } \`` ) ;
516
+ }
517
+ }
448
518
this . renderDocsLine ( method ) ;
449
519
this . code . line ( ) ;
520
+ if ( method . protected ) {
521
+ this . code . line ( '*Protected method*' ) ;
522
+ this . code . line ( ) ;
523
+ }
450
524
451
525
this . renderMethodParameters ( method ) ;
452
526
453
527
// @return doc
454
528
if ( method . docs && method . docs . return ) {
455
- this . code . line ( `:return: ${ method . docs . return } ` ) ;
529
+ const [ firstLine , ...rest ] = method . docs . return . split ( '\n' ) ;
530
+ this . code . line ( `:return: ${ firstLine } ` ) ;
531
+ rest . forEach ( line => this . code . line ( ` ${ line } ` ) ) ;
456
532
}
457
533
458
534
if ( method . returns ) {
@@ -542,7 +618,7 @@ class SphinxDocsGenerator extends Generator {
542
618
} else {
543
619
throw new Error ( 'Unexpected type ref' ) ;
544
620
}
545
- if ( type . optional ) { result . ref = `${ result . ref } or undefined` ; }
621
+ if ( type . optional ) { result . ref = `${ result . ref } or \`\` undefined\`\` ` ; }
546
622
return result ;
547
623
548
624
// Wrap a string between parenthesis if it contains " or "
@@ -552,12 +628,28 @@ class SphinxDocsGenerator extends Generator {
552
628
}
553
629
}
554
630
555
- private renderProperty ( prop : spec . Property ) {
631
+ private renderProperty ( prop : spec . Property , inheritedFrom ?: string ) {
556
632
this . code . line ( ) ;
557
633
const type = this . renderTypeRef ( prop . type ) ;
558
634
this . code . openBlock ( `.. py:attribute:: ${ prop . name } ` ) ;
635
+ if ( inheritedFrom ) {
636
+ this . code . line ( ) ;
637
+ this . code . line ( `*Inherited from* :py:attr:\`${ inheritedFrom } <${ inheritedFrom } .${ prop . name } >\`` ) ;
638
+ } else if ( prop . overrides ) {
639
+ this . code . line ( ) ;
640
+ const superType = this . findType ( prop . overrides . fqn ) as spec . ClassType | spec . InterfaceType ;
641
+ if ( spec . isInterfaceType ( superType ) || superType . properties ! . find ( p => p . name === prop . name && ! ! p . abstract ) ) {
642
+ this . code . line ( `*Implements* :py:meth:\`${ prop . overrides . fqn } .${ prop . name } \`` ) ;
643
+ } else {
644
+ this . code . line ( `*Overrides* :py:attr:\`${ prop . overrides . fqn } .${ prop . name } \`` ) ;
645
+ }
646
+ }
559
647
this . renderDocsLine ( prop ) ;
560
648
this . code . line ( ) ;
649
+ if ( prop . protected ) {
650
+ this . code . line ( '*Protected property*' ) ;
651
+ this . code . line ( ) ;
652
+ }
561
653
const readonly = prop . immutable ? ' *(readonly)*' : '' ;
562
654
const abs = prop . abstract ? ' *(abstract)*' : '' ;
563
655
const stat = prop . static ? ' *(static)*' : '' ;
@@ -665,3 +757,5 @@ function formatLanguage(language: string): string {
665
757
return language ;
666
758
}
667
759
}
760
+
761
+ type InheritedMembers = { [ typeFqn : string ] : { methods : spec . Method [ ] , properties : spec . Property [ ] } } ;
0 commit comments