private void CreateCompositionHost(InitializeParams initializeParams) { _environment = new OmniSharpEnvironment( Helpers.FromUri(initializeParams.RootUri), Convert.ToInt32(initializeParams.ProcessId ?? -1L), GetLogLevel(initializeParams.Trace), _application.OtherArgs.ToArray()); // TODO: Make this work with logger factory differently // Maybe create a child logger factory? _loggerFactory.AddProvider(_server, _environment); _logger = _loggerFactory.CreateLogger <LanguageServerHost>(); var configurationRoot = new ConfigurationBuilder(_environment).Build(); var eventEmitter = new LanguageServerEventEmitter(_server); _serviceProvider = CompositionHostBuilder.CreateDefaultServiceProvider(_environment, configurationRoot, eventEmitter, _services); var plugins = _application.CreatePluginAssemblies(); var assemblyLoader = _serviceProvider.GetRequiredService <IAssemblyLoader>(); var compositionHostBuilder = new CompositionHostBuilder(_serviceProvider) .WithOmniSharpAssemblies() .WithAssemblies(typeof(LanguageServerHost).Assembly) .WithAssemblies(assemblyLoader.LoadByAssemblyNameOrPath(plugins.AssemblyNames).ToArray()); _compositionHost = compositionHostBuilder.Build(); var projectSystems = _compositionHost.GetExports <IProjectSystem>(); var documentSelectors = projectSystems .GroupBy(x => x.Language) .Select(x => ( language: x.Key, selector: new DocumentSelector(x .SelectMany(z => z.Extensions) .Distinct() .Select(z => new DocumentFilter() { Pattern = $"**/*{z}" })) )); _logger.LogTrace( "Configured Document Selectors {@DocumentSelectors}", documentSelectors.Select(x => new { x.language, x.selector }) ); // TODO: Get these with metadata so we can attach languages // This will thne let us build up a better document filter, and add handles foreach type of handler // This will mean that we will have a strategy to create handlers from the interface type _handlers = new RequestHandlers( _compositionHost.GetExports <Lazy <IRequestHandler, OmniSharpRequestHandlerMetadata> >(), documentSelectors ); _logger.LogTrace("--- Handler Definitions ---"); foreach (var handlerCollection in _handlers) { foreach (var handler in handlerCollection) { _logger.LogTrace( "Handler: {Language}:{DocumentSelector}:{Handler}", handlerCollection.Language, handlerCollection.DocumentSelector.ToString(), handler.GetType().FullName ); } } _logger.LogTrace("--- Handler Definitions ---"); }
internal static RequestHandlers ConfigureCompositionHost(ILanguageServer server, CompositionHost compositionHost) { var projectSystems = compositionHost.GetExports <IProjectSystem>(); var documentSelectors = projectSystems .GroupBy(x => x.Language) .Select(x => ( language: x.Key, selector: new DocumentSelector(x .SelectMany(z => z.Extensions) .Distinct() .SelectMany(z => { if (x.Key == LanguageNames.CSharp && z == ".cs") { return(new[] { new DocumentFilter() { Pattern = $"**/*{z}" }, new DocumentFilter() { Scheme = "csharp" } }); } return(new[] { new DocumentFilter() { Pattern = $"**/*{z}" }, }); }) ) )) .ToArray(); var logger = compositionHost.GetExport <ILoggerFactory>().CreateLogger <LanguageServerHost>(); logger.LogTrace( "Configured Document Selectors {@DocumentSelectors}", documentSelectors.Select(x => new { x.language, x.selector }) ); var omnisharpRequestHandlers = compositionHost.GetExports <Lazy <IRequestHandler, OmniSharpRequestHandlerMetadata> >(); // TODO: Get these with metadata so we can attach languages // This will then let us build up a better document filter, and add handles foreach type of handler // This will mean that we will have a strategy to create handlers from the interface type var handlers = new RequestHandlers(omnisharpRequestHandlers, documentSelectors); logger.LogTrace("--- Handler Definitions ---"); foreach (var handlerCollection in handlers) { foreach (var handler in handlerCollection) { logger.LogTrace( "Handler: {Language}:{DocumentSelector}:{Handler}", handlerCollection.Language, handlerCollection.DocumentSelector.ToString(), handler.GetType().FullName ); } } // the goal here is add interoperability between omnisharp and LSP // This way an existing client (say vscode) that is using the custom omnisharp protocol can migrate to the new one // and not loose any functionality. server.Register(r => { var defaultOptions = new JsonRpcHandlerOptions() { RequestProcessType = RequestProcessType.Parallel }; var interop = InitializeInterop(compositionHost); foreach (var osHandler in interop) { var method = $"o#/{osHandler.Key.Trim('/').ToLowerInvariant()}"; r.OnJsonRequest(method, CreateInteropHandler(osHandler.Value), defaultOptions); logger.LogTrace("O# Handler: {Method}", method); }