import * as path from 'path' ; import * as tsdoc from '@microsoft/tsdoc' ; import colors from 'colors' ; import { CommandLineAction , CommandLineStringParameter } from '@rushstack/ts-command-line' ; import { FileSystem } from '@rushstack/node-core-library' ; import { ApiModel , ApiItem , ApiItemContainerMixin , ApiDocumentedItem , IResolveDeclarationReferenceResult } from '@microsoft/api-extractor-model' ; export interface IBuildApiModelResult { apiModel : ApiModel ; inputFolder : string ; outputFolder : string ; } export abstract class BaseAction extends CommandLineAction { private _inputFolderParameter ! : CommandLineStringParameter ; private _outputFolderParameter ! : CommandLineStringParameter ; protected onDefineParameters ( ) { this . _inputFolderParameter = this . defineStringParameter ( { parameterLongName : '--input-folder' , parameterShortName : '-i' , argumentName : 'FOLDER1' , description : `Specifies the input folder containing the *.api.json files to be processed.` + ` If omitted, the default is "./input"` } ) ; this . _outputFolderParameter = this . defineStringParameter ( { parameterLongName : '--output-folder' , parameterShortName : '-o' , argumentName : 'FOLDER2' , description : `Specifies the output folder where the documentation will be written.` + ` ANY EXISTING CONTENTS WILL BE DELETED!` + ` If omitted, the default is "./${ this . actionName }"` } ) ; } protected buildApiModel ( ) { const apiModel = new ApiModel ( ) ; const inputFolder = this . _inputFolderParameter . value || './input' ; if ( ! FileSystem . exists ( inputFolder ) ) { throw new Error ( 'The input folder does not exist: ' + inputFolder ) ; } const outputFolder = this . _outputFolderParameter . value || `./${ this . actionName }` ; FileSystem . ensureFolder ( outputFolder ) ; for ( const filename of FileSystem . readFolderItemNames ( inputFolder ) ) { if ( filename . match ( /\.api\.json$/i ) ) { console . log ( `Reading ${ filename }` ) ; const filenamePath = path . join ( inputFolder , filename ) ; apiModel . loadPackage ( filenamePath ) ; } } this . _applyInheritDoc ( apiModel , apiModel ) ; return { apiModel , inputFolder , outputFolder } ; } private _applyInheritDoc ( apiItem , apiModel ) { if ( apiItem instanceof ApiDocumentedItem ) { if ( apiItem . tsdocComment ) { const inheritDocTag = apiItem . tsdocComment . inheritDocTag ; if ( inheritDocTag && inheritDocTag . declarationReference ) { const result = apiModel . resolveDeclarationReference ( inheritDocTag . declarationReference , apiItem ) ; if ( result . errorMessage ) { console . log ( colors . yellow ( `Warning: Unresolved @inheritDoc tag for ${ apiItem . displayName }: ` + result . errorMessage ) ) ; } else { if ( result . resolvedApiItem instanceof ApiDocumentedItem && result . resolvedApiItem . tsdocComment && result . resolvedApiItem !== apiItem ) { this . _copyInheritedDocs ( apiItem . tsdocComment , result . resolvedApiItem . tsdocComment ) ; } } } } } if ( ApiItemContainerMixin . isBaseClassOf ( apiItem ) ) { for ( const member of apiItem . members ) { this . _applyInheritDoc ( member , apiModel ) ; } } } /**
     * Copy the content from `sourceDocComment` to `targetDocComment`.
     * This code is borrowed from DocCommentEnhancer as a temporary workaround.
     */ private _copyInheritedDocs ( targetDocComment , sourceDocComment ) { targetDocComment . summarySection = sourceDocComment . summarySection ; targetDocComment . remarksBlock = sourceDocComment . remarksBlock ; targetDocComment . params . clear ( ) ; for ( const param of sourceDocComment . params ) { targetDocComment . params . add ( param ) ; } for ( const typeParam of sourceDocComment . typeParams ) { targetDocComment . typeParams . add ( typeParam ) ; } targetDocComment . returnsBlock = sourceDocComment . returnsBlock ; targetDocComment . inheritDocTag = undefined ; } }