import { difference , each , filter , forIn , has , keys , map , startsWith } from 'lodash' ; import { Models , ScriptCs } from 'omnisharp-client' ; import { Observable , ReplaySubject } from 'rxjs' ; import { IProjectViewModel } from '../omnisharp' ; const projectFactories = { MsBuildProject : < any > MsBuildProjectViewModel , DotNetProject : < any > DotNetProjectViewModel } ; const supportedProjectTypes = keys ( projectFactories ) ; export function projectViewModelFactory ( omnisharpProject , solutionPath ) { const projectTypes = filter ( supportedProjectTypes , type => has ( omnisharpProject , type ) ) ; const missing = difference ( keys ( omnisharpProject ) , supportedProjectTypes ) ; if ( missing . length ) { console . log ( `Missing factory for project type ${ missing }` ) ; } const results = [ ] ; let skipDnx = false ; if ( projectTypes [ 'DotNetProject' ] && projectTypes [ 'DnxProject' ] ) { skipDnx = true ; } each ( projectTypes , projectType => { if ( skipDnx && startsWith ( projectType , 'Dnx' ) ) { return ; } if ( projectType && projectFactories [ projectType ] ) { results . push ( new projectFactories [ projectType ] ( omnisharpProject [ projectType ] , solutionPath ) ) ; } } ) ; return results ; } const workspaceFactories = { MsBuild : ( workspace , solutionPath ) => { return map ( workspace . Projects , projectInformation => new MsBuildProjectViewModel ( projectInformation , solutionPath ) ) ; } , DotNet : ( workspace , solutionPath ) => { return map ( workspace . Projects , projectInformation => new DotNetProjectViewModel ( projectInformation , solutionPath ) ) ; } , ScriptCs : ( workspace , solutionPath ) => { return [ ] ; } , } ; export function workspaceViewModelFactory ( omnisharpWorkspace , solutionPath ) { const projects = [ ] ; let skipDnx = false ; if ( omnisharpWorkspace [ 'DotNet' ] && omnisharpWorkspace [ 'Dnx' ] ) skipDnx = true ; forIn ( omnisharpWorkspace , ( item , key ) => { const factory = workspaceFactories [ key ] ; if ( skipDnx && startsWith ( key , 'Dnx' ) ) return ; if ( factory ) { projects . push ( ... factory ( item , solutionPath ) ) ; } } ) ; return projects ; } export abstract class ProjectViewModel < T > implements IProjectViewModel { constructor ( project , solutionPath ) { this . solutionPath = solutionPath ; this . init ( project ) ; this . observe = { activeFramework : < Observable < Models . DotNetFramework > > < any > this . _subjectActiveFramework } ; this . _subjectActiveFramework . next ( this . _frameworks [ 0 ] ) ; } private _name : string ; public get name ( ) { return this . _name ; } public set name ( value ) { this . _name = value ; } private _path : string ; public get path ( ) { return this . _path ; } public set path ( value ) { this . _path = value ; } private _solutionPath : string ; public get solutionPath ( ) { return this . _solutionPath ; } public set solutionPath ( value ) { this . _solutionPath = value ; } private _sourceFiles : string [ ] = [ ] ; public get sourceFiles ( ) { return this . _sourceFiles ; } public set sourceFiles ( value ) { this . _sourceFiles = value || [ ] ; if ( this . _filesSet ) this . _filesSet = null ; } private _filesSet : Set < string > ; public get filesSet ( ) { if ( ! this . _filesSet ) { this . _filesSet = new Set < string > ( ) ; each ( this . _sourceFiles , file => { this . _filesSet . add ( file ) ; } ) ; } return this . _filesSet ; } private _subjectActiveFramework = new ReplaySubject < Models . DotNetFramework > ( 1 ) ; private _activeFramework : Models . DotNetFramework ; public get activeFramework ( ) { if ( ! this . _activeFramework ) { this . _activeFramework = this . frameworks [ 0 ] ; } return this . _activeFramework ; } public set activeFramework ( value ) { this . _activeFramework = value ; if ( ! this . _subjectActiveFramework . closed ) { this . _subjectActiveFramework . next ( this . _activeFramework ) ; } } private _frameworks : Models . DotNetFramework [ ] = [ { FriendlyName : 'All' , Name : 'all' , ShortName : 'all' } ] ; public get frameworks ( ) { return this . _frameworks ; } public set frameworks ( value ) { this . _frameworks = [ { FriendlyName : 'All' , Name : 'all' , ShortName : 'all' } ] . concat ( value ) ; if ( ! this . activeFramework ) { this . activeFramework = this . _frameworks [ 0 ] ; } } private _configurations : string [ ] = [ ] ; public get configurations ( ) { return this . _configurations ; } public set configurations ( value ) { this . _configurations = value || [ ] ; } public observe : { activeFramework : Observable < Models . DotNetFramework > ; } ; public abstract init ( value ) ; public update ( other ) { this . name = other . name ; this . path = other . path ; this . solutionPath = other . solutionPath ; this . sourceFiles = other . sourceFiles ; this . frameworks = other . frameworks ; this . activeFramework = this . _activeFramework ; this . configurations = other . configurations ; } public toJSON ( ) { const { name , path , solutionPath , sourceFiles , frameworks , configurations } = this ; return { name , path , solutionPath , sourceFiles , frameworks , configurations } ; } public dispose ( ) { this . _subjectActiveFramework . unsubscribe ( ) ; } } export class EmptyProjectViewModel extends ProjectViewModel < ProjectViewModel < any > > { public init ( project ) { } } class ProxyProjectViewModel extends ProjectViewModel < ProjectViewModel < any > > { public init ( project ) { this . update ( project ) ; } } class MsBuildProjectViewModel extends ProjectViewModel < Models . MSBuildProject > { public init ( project ) { const frameworks = [ { FriendlyName : project . TargetFramework , Name : project . TargetFramework , ShortName : project . TargetFramework } ] ; this . name = project . AssemblyName ; this . path = project . Path ; this . frameworks = frameworks ; this . sourceFiles = project . SourceFiles ; } } class DotNetProjectViewModel extends ProjectViewModel < Models . DotNetProjectInformation > { public init ( project ) { this . name = project . Name ; this . path = project . Path ; this . frameworks = project . Frameworks || [ ] ; this . configurations = ( project . Configurations || [ ] ) . map ( x => x . Name ) ; this . sourceFiles = project . SourceFiles || [ ] ; } } class ScriptCsProjectViewModel extends ProjectViewModel < ScriptCs . ScriptCsContextModel > { public init ( project ) { this . name = 'ScriptCs' ; this . path = project . RootPath ; this . sourceFiles = project . CsxFilesBeingProcessed ; } }