import ts from 'typescript' ; import { File } from './Components/File' ; import { PlantUMLFormat } from './Formatter/PlantUMLFormat' ; import { ComponentKind } from './Models/ComponentKind' ; import { Formatter } from './Models/Formatter' ; import { IComponentComposite } from './Models/IComponentComposite' ; import { Class } from './Components/Class' ; import { FileFactory } from './Factories/FileFactory' ; import { MermaidFormat } from './Formatter/MermaidFormat' ; import { ICommandOptions } from './Models/ICommandOptions' ; export namespace tplant { export function generateDocumentation ( fileNames , options = ts . getDefaultCompilerOptions ( ) ) { const program = ts . createProgram ( fileNames , options ) ; const checker = program . getTypeChecker ( ) ; const result = [ ] ; program . getSourceFiles ( ) . forEach ( ( sourceFile ) : void => { if ( ! sourceFile . isDeclarationFile ) { const file = FileFactory . create ( sourceFile , checker ) ; if ( file !== undefined ) { result . push ( file ) ; } } } ) ; return result ; } export function convertToPlant ( files , options = { associations : false , onlyInterfaces : false , format : 'plantuml' , onlyClasses : false } ) { let formatter ; if ( options . format === 'mermaid' ) { formatter = new MermaidFormat ( options ) ; } else { formatter = new PlantUMLFormat ( options ) ; } if ( options . onlyClasses ) { for ( const file of files ) { ( < File > file ) . parts = ( < File > file ) . parts . filter ( ( part ) : boolean => part . componentKind === ComponentKind . CLASS ) ; } } else if ( options . onlyInterfaces ) { for ( const file of files ) { ( < File > file ) . parts = ( < File > file ) . parts . filter ( ( part ) : boolean => part . componentKind === ComponentKind . INTERFACE ) ; } } else if ( options . targetClass !== undefined ) { const target = < Class > findClass ( files , options . targetClass ) ; const parts = [ ] ; if ( target !== undefined ) { parts . push ( target ) ; let parent = target . extendsClass ; while ( parent !== undefined ) { const parentClass = < Class > findClass ( files , parent ) ; parts . push ( parentClass ) ; parts . push ( ... getInterfaces ( files , parentClass ) ) ; parent = parentClass . extendsClass ; } parts . push ( ... getInterfaces ( files , target ) ) ; parts . push ( ... findChildClass ( files , target ) ) ; } return formatter . renderFiles ( parts , false ) ; } return formatter . renderFiles ( files , options . associations ) ; } function getInterfaces ( files , comp ) { const res = [ ] ; comp . implementsInterfaces . forEach ( ( impl ) => { const implComponent = findClass ( files , impl ) ; if ( implComponent !== undefined ) { res . push ( implComponent ) ; } } ) ; return res ; } function findClass ( files , name ) { for ( const file of files ) { for ( const part of ( < File > file ) . parts ) { if ( part . name === name ) { return part ; } } } return undefined ; } function findChildClass ( files , comp ) { const res = [ ] ; for ( const file of files ) { ( < File > file ) . parts . forEach ( ( part ) : void => { if ( part instanceof Class && ( part ) . extendsClass === comp . name ) { res . push ( part ) ; part . implementsInterfaces = [ ] ; res . push ( ... findChildClass ( files , part ) ) ; } } ) ; } return res ; } }