import * as tsc from "typescript" ; import { HashMap } from "tstl/container/HashMap" ; import { HashSet } from "tstl/container/HashSet" ; import { GenericAnalyzer } from "./GenericAnalyzer" ; export namespace ImportAnalyzer { export interface IOutput { features : [ string , string [ ] ] [ ] ; alias : string ; } export type Dictionary = HashMap < string , HashSet < string > > ; export function analyze ( checker , genericDict , importDict , type ) { return explore ( checker , genericDict , importDict , type ) ; } function explore ( checker , genericDict , importDict , type ) { while ( genericDict . has ( type ) === true ) type = genericDict . get ( type ) ! ; const symbol = type . getSymbol ( ) || type . aliasSymbol ; if ( symbol === undefined ) return checker . typeToString ( type , undefined , undefined ) ; else if ( type . aliasSymbol === undefined && type . isUnionOrIntersection ( ) ) { const joiner = type . isIntersection ( ) ? " & " : " | " ; return type . types . map ( child => explore ( checker , genericDict , importDict , child ) ) . join ( joiner ) ; } const name = get_name ( symbol ) ; const sourceFile = symbol . declarations ! [ 0 ] . getSourceFile ( ) ; if ( sourceFile . fileName . indexOf ( "typescript/lib" ) === - 1 ) { let it = importDict . find ( sourceFile . fileName ) ; if ( it . equals ( importDict . end ( ) ) === true ) it = importDict . emplace ( sourceFile . fileName , new HashSet ( ) ) . first ; it . second . insert ( name . split ( "." ) [ 0 ] ) ; } const generic = checker . getTypeArguments ( type as tsc . TypeReference ) ; if ( generic . length ) { return name === "Promise" ? explore ( checker , genericDict , importDict , generic [ 0 ] ) : `${ name }<${ generic . map ( child => explore ( checker , genericDict , importDict , child ) ) . join ( ", " ) }>` ; } else return name ; } function get_name ( symbol ) { let name = symbol . escapedName . toString ( ) ; let decl = symbol . getDeclarations ( ) ! [ 0 ] . parent ; while ( tsc . isModuleBlock ( decl ) ) { name = `${ decl . parent . name . getText ( ) }.${ name }` ; decl = decl . parent . parent ; } return name ; } }