import ts from 'typescript' ; import { Method } from '../Components/Method' ; import { Property } from '../Components/Property' ; import { TypeParameter } from '../Components/TypeParameter' ; import { IComponentComposite } from '../Models/IComponentComposite' ; import { Modifier } from '../Models/Modifier' ; import { ClassFactory } from './ClassFactory' ; import { EnumFactory } from './EnumFactory' ; import { InterfaceFactory } from './InterfaceFactory' ; import { MethodFactory } from './MethodFactory' ; import { NamespaceFactory } from './NamespaceFactory' ; import { PropertyFactory } from './PropertyFactory' ; import { TypeParameterFactory } from './TypeParameterFactory' ; export namespace ComponentFactory { export function isNodeExported ( node ) { return ( node . flags & ts . ModifierFlags . Export ) !== 0 || node . parent . kind === ts . SyntaxKind . SourceFile || node . parent . kind === ts . SyntaxKind . ModuleBlock ; } export function create ( node , checker ) { const componentComposites = [ ] ; ts . forEachChild ( node , ( childNode ) => { if ( ! isNodeExported ( childNode ) ) { return ; } if ( childNode . kind === ts . SyntaxKind . ClassDeclaration ) { const currentNode = < ts . ClassLikeDeclarationBase > childNode ; if ( currentNode . name === undefined ) { return ; } const classSymbol = checker . getSymbolAtLocation ( currentNode . name ) ; if ( classSymbol === undefined ) { return ; } componentComposites . push ( ClassFactory . create ( classSymbol , checker ) ) ; } else if ( childNode . kind === ts . SyntaxKind . InterfaceDeclaration ) { const currentNode = < ts . InterfaceDeclaration > childNode ; const interfaceSymbol = checker . getSymbolAtLocation ( currentNode . name ) ; if ( interfaceSymbol === undefined ) { return ; } componentComposites . push ( InterfaceFactory . create ( interfaceSymbol , checker ) ) ; } else if ( childNode . kind === ts . SyntaxKind . ModuleDeclaration ) { const currentNode = < ts . NamespaceDeclaration > childNode ; const namespaceSymbol = checker . getSymbolAtLocation ( currentNode . name ) ; if ( namespaceSymbol === undefined ) { return ; } componentComposites . push ( NamespaceFactory . create ( namespaceSymbol , checker ) ) ; } else if ( childNode . kind === ts . SyntaxKind . EnumDeclaration ) { const currentNode = < ts . EnumDeclaration > childNode ; const enumSymbol = checker . getSymbolAtLocation ( currentNode . name ) ; if ( enumSymbol === undefined ) { return ; } componentComposites . push ( EnumFactory . create ( enumSymbol ) ) ; return ; } } ) ; return componentComposites ; } function getModifier ( modifiers ) { for ( const modifier of modifiers ) { if ( modifier . kind === ts . SyntaxKind . PrivateKeyword ) { return 'private' ; } if ( modifier . kind === ts . SyntaxKind . PublicKeyword ) { return 'public' ; } if ( modifier . kind === ts . SyntaxKind . ProtectedKeyword ) { return 'protected' ; } } return 'public' ; } export function getExtendsHeritageClauseNames ( heritageClause ) { return heritageClause . types . map ( getInterfaceName ) ; } function getInterfaceName ( nodeObject ) { return ( < ts . Identifier > nodeObject . expression ) . text ; } export function getImplementsHeritageClauseNames ( heritageClause ) { return heritageClause . types . map ( getInterfaceName ) ; } function isMethod ( declaration ) { return declaration . kind === ts . SyntaxKind . MethodDeclaration || declaration . kind === ts . SyntaxKind . MethodSignature ; } function isProperty ( declaration ) { return declaration . kind === ts . SyntaxKind . PropertySignature || declaration . kind === ts . SyntaxKind . PropertyDeclaration || declaration . kind === ts . SyntaxKind . GetAccessor || declaration . kind === ts . SyntaxKind . SetAccessor || declaration . kind === ts . SyntaxKind . Parameter ; } function isTypeParameter ( declaration ) { return declaration . kind === ts . SyntaxKind . TypeParameter ; } export function getMemberModifier ( memberDeclaration ) { const memberModifiers = memberDeclaration . modifiers ; if ( memberModifiers === undefined ) { return 'public' ; } return getModifier ( memberModifiers ) ; } export function isAbstract ( memberDeclaration ) { const memberModifiers = memberDeclaration . modifiers ; if ( memberModifiers !== undefined ) { for ( const memberModifier of memberModifiers ) { if ( memberModifier . kind === ts . SyntaxKind . AbstractKeyword ) { return true ; } } } return false ; } export function isStatic ( memberDeclaration ) { const memberModifiers = memberDeclaration . modifiers ; if ( memberModifiers !== undefined ) { for ( const memberModifier of memberModifiers ) { if ( memberModifier . kind === ts . SyntaxKind . StaticKeyword ) { return true ; } } } return false ; } export function serializeMethods ( memberSymbols , checker ) { const result = [ ] ; if ( memberSymbols !== undefined ) { memberSymbols . forEach ( ( memberSymbol ) : void => { const memberDeclarations = memberSymbol . getDeclarations ( ) ; if ( memberDeclarations === undefined ) { return ; } memberDeclarations . forEach ( ( memberDeclaration ) : void => { if ( isMethod ( memberDeclaration ) ) { result . push ( MethodFactory . create ( memberSymbol , memberDeclaration , checker ) ) ; } else if ( isProperty ( memberDeclaration ) ) { result . push ( PropertyFactory . create ( memberSymbol , memberDeclaration , checker ) ) ; } } ) ; } ) ; } return result ; } export function serializeTypeParameters ( memberSymbols , checker ) { const result = [ ] ; if ( memberSymbols !== undefined ) { memberSymbols . forEach ( ( memberSymbol ) : void => { const memberDeclarations = memberSymbol . getDeclarations ( ) ; if ( memberDeclarations === undefined ) { return ; } memberDeclarations . forEach ( ( memberDeclaration ) : void => { if ( isTypeParameter ( memberDeclaration ) ) { result . push ( TypeParameterFactory . create ( memberSymbol , memberDeclaration , checker ) ) ; } } ) ; } ) ; } return result ; } export function hasInitializer ( declaration ) { return declaration . initializer !== undefined ; } export function isOptional ( declaration ) { return declaration . questionToken !== undefined ; } }