@@ -36,7 +36,10 @@ import {
3636 ApiTypeParameterListMixin ,
3737 Excerpt ,
3838 ExcerptToken ,
39- ExcerptTokenKind
39+ ExcerptTokenKind ,
40+ HeritageType ,
41+ ApiVariable ,
42+ ApiTypeAlias
4043} from '@microsoft/api-extractor-model' ;
4144import {
4245 DeclarationReference ,
@@ -49,7 +52,8 @@ import {
4952 IYamlSyntax ,
5053 IYamlParameter ,
5154 IYamlReference ,
52- IYamlReferenceSpec
55+ IYamlReferenceSpec ,
56+ IYamlInheritanceTree
5357} from '../yaml/IYamlApiFile' ;
5458import {
5559 IYamlTocFile ,
@@ -72,6 +76,11 @@ const enum FlattenMode {
7276 NoNamespaces
7377}
7478
79+ interface INameOptions {
80+ includeSignature ?: boolean ;
81+ includeNamespace ?: boolean ;
82+ }
83+
7584/**
7685 * Writes documentation in the Universal Reference YAML file format, as defined by typescript.schema.json.
7786 */
@@ -172,10 +181,13 @@ export class YamlDocumenter {
172181 this . _writeYamlFile ( newYamlFile , yamlFilePath , 'UniversalReference' , yamlApiSchema ) ;
173182
174183 if ( parentYamlFile ) {
184+ // References should be recorded in the parent YAML file with the local name of the embedded item.
185+ // This avoids unnecessary repetition when listing items inside of a namespace.
175186 this . _recordYamlReference (
176187 this . _ensureYamlReferences ( ) ,
177188 this . _getUid ( apiItem ) ,
178- this . _getYamlItemName ( apiItem , /*includeSignature*/ true ) ) ;
189+ this . _getYamlItemName ( apiItem , { includeSignature : true } ) ,
190+ this . _getYamlItemName ( apiItem , { includeNamespace : true , includeSignature : true } ) ) ;
179191 }
180192 }
181193
@@ -202,17 +214,19 @@ export class YamlDocumenter {
202214 private _flattenNamespaces ( items : ReadonlyArray < ApiItem > , childrenOut : ApiItem [ ] , mode : FlattenMode ) : boolean {
203215 let hasNonNamespaceChildren : boolean = false ;
204216 for ( const item of items ) {
205- if ( item . kind === ApiItemKind . Namespace && mode !== FlattenMode . NoNamespaces ) {
206- // At any level, always include a nested namespace if it has non-namespace children, but do not include its
207- // non-namespace children in the result.
217+ if ( item . kind === ApiItemKind . Namespace ) {
218+ if ( mode !== FlattenMode . NoNamespaces ) {
219+ // At any level, always include a nested namespace if it has non-namespace children, but do not include its
220+ // non-namespace children in the result.
208221
209- // Record the offset at which the namespace is added in case we need to remove it later.
210- const index : number = childrenOut . length ;
211- childrenOut . push ( item ) ;
222+ // Record the offset at which the namespace is added in case we need to remove it later.
223+ const index : number = childrenOut . length ;
224+ childrenOut . push ( item ) ;
212225
213- if ( ! this . _flattenNamespaces ( item . members , childrenOut , FlattenMode . NestedNamespacesOnly ) ) {
214- // This namespace had no non-namespace children, remove it.
215- childrenOut . splice ( index , 1 ) ;
226+ if ( ! this . _flattenNamespaces ( item . members , childrenOut , FlattenMode . NestedNamespacesOnly ) ) {
227+ // This namespace had no non-namespace children, remove it.
228+ childrenOut . splice ( index , 1 ) ;
229+ }
216230 }
217231 } else if ( this . _shouldInclude ( item . kind ) ) {
218232 if ( mode !== FlattenMode . NestedNamespacesOnly ) {
@@ -278,10 +292,10 @@ export class YamlDocumenter {
278292 if ( apiItem . kind === ApiItemKind . Package ) {
279293 name = PackageName . getUnscopedName ( apiItem . displayName ) ;
280294 } else {
281- name = this . _getYamlItemName ( apiItem , /*includeSignature*/ false ) ;
295+ name = this . _getYamlItemName ( apiItem ) ;
282296 }
283297
284- if ( apiItem . getMergedSiblings ( ) . length > 1 ) {
298+ if ( name === apiItem . displayName && apiItem . getMergedSiblings ( ) . length > 1 ) {
285299 name += ` (${ apiItem . kind } )` ;
286300 }
287301
@@ -306,8 +320,6 @@ export class YamlDocumenter {
306320 case ApiItemKind . CallSignature :
307321 case ApiItemKind . ConstructSignature :
308322 case ApiItemKind . IndexSignature :
309- case ApiItemKind . TypeAlias :
310- case ApiItemKind . Variable :
311323 return false ;
312324 }
313325 return true ;
@@ -354,11 +366,16 @@ export class YamlDocumenter {
354366 }
355367 }
356368
357- yamlItem . name = this . _getYamlItemName ( apiItem , /*includeSignature*/ true ) ;
358-
359- yamlItem . fullName = yamlItem . name ;
369+ yamlItem . name = this . _getYamlItemName ( apiItem , { includeSignature : true } ) ;
370+ yamlItem . fullName = this . _getYamlItemName ( apiItem , { includeSignature : true , includeNamespace : true } ) ;
360371 yamlItem . langs = [ 'typeScript' ] ;
361372
373+ // Add the namespace of the item if it is contained in one.
374+ // Do not add the namespace parent of a namespace as they are flattened in the documentation.
375+ if ( apiItem . kind !== ApiItemKind . Namespace && apiItem . parent && apiItem . parent . kind === ApiItemKind . Namespace ) {
376+ yamlItem . namespace = apiItem . parent . canonicalReference . toString ( ) ;
377+ }
378+
362379 switch ( apiItem . kind ) {
363380 case ApiItemKind . Enum :
364381 yamlItem . type = 'enum' ;
@@ -413,6 +430,16 @@ export class YamlDocumenter {
413430 this . _populateYamlFunctionLike ( uid , yamlItem , apiItem as ApiFunction ) ;
414431 break ;
415432
433+ case ApiItemKind . Variable :
434+ yamlItem . type = 'variable' ;
435+ this . _populateYamlVariable ( uid , yamlItem , apiItem as ApiVariable ) ;
436+ break ;
437+
438+ case ApiItemKind . TypeAlias :
439+ yamlItem . type = 'typealias' ;
440+ this . _populateYamlTypeAlias ( uid , yamlItem , apiItem as ApiTypeAlias ) ;
441+ break ;
442+
416443 default :
417444 throw new Error ( 'Unimplemented item kind: ' + apiItem . kind ) ;
418445 }
@@ -456,6 +483,7 @@ export class YamlDocumenter {
456483 if ( apiItem instanceof ApiClass ) {
457484 if ( apiItem . extendsType ) {
458485 yamlItem . extends = [ this . _renderType ( uid , apiItem . extendsType . excerpt ) ] ;
486+ yamlItem . inheritance = this . _renderInheritance ( uid , [ apiItem . extendsType ] ) ;
459487 }
460488 if ( apiItem . implementsTypes . length > 0 ) {
461489 yamlItem . implements = [ ] ;
@@ -469,6 +497,7 @@ export class YamlDocumenter {
469497 for ( const extendsType of apiItem . extendsTypes ) {
470498 yamlItem . extends . push ( this . _renderType ( uid , extendsType . excerpt ) ) ;
471499 }
500+ yamlItem . inheritance = this . _renderInheritance ( uid , apiItem . extendsTypes ) ;
472501 }
473502
474503 const typeParameters : IYamlParameter [ ] = this . _populateYamlTypeParameters ( uid , apiItem ) ;
@@ -565,6 +594,41 @@ export class YamlDocumenter {
565594 }
566595 }
567596
597+ private _populateYamlVariable ( uid : DeclarationReference , yamlItem : Partial < IYamlItem > , apiItem : ApiVariable ) :
598+ void {
599+
600+ const syntax : IYamlSyntax = {
601+ content : apiItem . getExcerptWithModifiers ( )
602+ } ;
603+ yamlItem . syntax = syntax ;
604+
605+ if ( apiItem . variableTypeExcerpt . text ) {
606+ syntax . return = {
607+ type : [ this . _renderType ( uid , apiItem . variableTypeExcerpt ) ]
608+ } ;
609+ }
610+ }
611+
612+ private _populateYamlTypeAlias ( uid : DeclarationReference , yamlItem : Partial < IYamlItem > , apiItem : ApiTypeAlias ) :
613+ void {
614+
615+ const syntax : IYamlSyntax = {
616+ content : apiItem . getExcerptWithModifiers ( )
617+ } ;
618+ yamlItem . syntax = syntax ;
619+
620+ const typeParameters : IYamlParameter [ ] = this . _populateYamlTypeParameters ( uid , apiItem ) ;
621+ if ( typeParameters . length ) {
622+ syntax . typeParameters = typeParameters ;
623+ }
624+
625+ if ( apiItem . typeExcerpt . text ) {
626+ syntax . return = {
627+ type : [ this . _renderType ( uid , apiItem . typeExcerpt ) ]
628+ } ;
629+ }
630+ }
631+
568632 private _renderMarkdown ( docSection : DocSection , contextApiItem : ApiItem ) : string {
569633 const stringBuilder : StringBuilder = new StringBuilder ( ) ;
570634
@@ -649,6 +713,30 @@ export class YamlDocumenter {
649713 return this . _yamlReferences ;
650714 }
651715
716+ private _renderInheritance ( contextUid : DeclarationReference , heritageTypes : ReadonlyArray < HeritageType > ) :
717+ IYamlInheritanceTree [ ] {
718+
719+ const result : IYamlInheritanceTree [ ] = [ ] ;
720+ for ( const heritageType of heritageTypes ) {
721+ const type : string = this . _renderType ( contextUid , heritageType . excerpt ) ;
722+ const yamlInheritance : IYamlInheritanceTree = { type } ;
723+ const apiItem : ApiItem | undefined = this . _apiItemsByCanonicalReference . get ( type ) ;
724+ if ( apiItem ) {
725+ if ( apiItem instanceof ApiClass ) {
726+ if ( apiItem . extendsType ) {
727+ yamlInheritance . inheritance = this . _renderInheritance ( this . _getUidObject ( apiItem ) , [ apiItem . extendsType ] ) ;
728+ }
729+ } else if ( apiItem instanceof ApiInterface ) {
730+ if ( apiItem . extendsTypes . length > 0 ) {
731+ yamlInheritance . inheritance = this . _renderInheritance ( this . _getUidObject ( apiItem ) , apiItem . extendsTypes ) ;
732+ }
733+ }
734+ }
735+ result . push ( yamlInheritance ) ;
736+ }
737+ return result ;
738+ }
739+
652740 private _renderType ( contextUid : DeclarationReference , typeExcerpt : Excerpt ) : string {
653741 const excerptTokens : ExcerptToken [ ] = typeExcerpt . tokens . slice (
654742 typeExcerpt . tokenRange . startIndex ,
@@ -686,10 +774,13 @@ export class YamlDocumenter {
686774 if ( excerptTokens . length === 1 &&
687775 excerptTokens [ 0 ] . kind === ExcerptTokenKind . Reference &&
688776 excerptTokens [ 0 ] . canonicalReference ) {
777+ const excerptRef : string = excerptTokens [ 0 ] . canonicalReference . toString ( ) ;
778+ const apiItem : ApiItem | undefined = this . _apiItemsByCanonicalReference . get ( excerptRef ) ;
689779 return this . _recordYamlReference (
690780 yamlReferences ,
691781 excerptTokens [ 0 ] . canonicalReference . toString ( ) ,
692- typeName
782+ apiItem ? this . _getYamlItemName ( apiItem ) : typeName ,
783+ apiItem ? this . _getYamlItemName ( apiItem , { includeNamespace : true } ) : typeName
693784 ) ;
694785 }
695786
@@ -711,10 +802,10 @@ export class YamlDocumenter {
711802 . withOverloadIndex ( undefined )
712803 . toString ( ) ;
713804
714- return this . _recordYamlReference ( yamlReferences , uid , typeName , excerptTokens ) ;
805+ return this . _recordYamlReference ( yamlReferences , uid , typeName , typeName , excerptTokens ) ;
715806 }
716807
717- private _recordYamlReference ( yamlReferences : IYamlReferences , uid : string , typeName : string ,
808+ private _recordYamlReference ( yamlReferences : IYamlReferences , uid : string , name : string , fullName : string ,
718809 excerptTokens ?: ExcerptToken [ ] ) : string {
719810
720811 if ( yamlReferences . references . some ( ref => ref . uid === uid ) ) {
@@ -758,17 +849,24 @@ export class YamlDocumenter {
758849 yamlReference . name = specs . map ( s => s . name ) . join ( '' ) . trim ( ) ;
759850 yamlReference . fullName = specs . map ( s => s . fullName || s . name ) . join ( '' ) . trim ( ) ;
760851 yamlReference [ 'spec.typeScript' ] = specs ;
761- } else if ( typeName !== uid ) {
762- yamlReference . name = typeName ;
852+ } else {
853+ if ( name !== uid ) {
854+ yamlReference . name = name ;
855+ }
856+ if ( fullName !== uid && fullName !== name ) {
857+ yamlReference . fullName = fullName ;
858+ }
763859 }
764860
765861 yamlReferences . references . push ( yamlReference ) ;
766862 return uid ;
767863 }
768864
769- private _getYamlItemName ( apiItem : ApiItem , includeSignature : boolean ) : string {
865+ private _getYamlItemName ( apiItem : ApiItem , options : INameOptions = { } ) : string {
866+ const { includeSignature, includeNamespace } = options ;
770867 const baseName : string = includeSignature ? Utilities . getConciseSignature ( apiItem ) : apiItem . displayName ;
771- if ( apiItem . parent && apiItem . parent . kind === ApiItemKind . Namespace ) {
868+ if ( ( includeNamespace || apiItem . kind === ApiItemKind . Namespace ) && apiItem . parent &&
869+ apiItem . parent . kind === ApiItemKind . Namespace ) {
772870 // If the immediate parent is a namespace, then add the namespaces to the name. For example:
773871 //
774872 // // Name: "N1"
0 commit comments