public async Task InitializeAsync() { var(client, server) = await Initialize(new TConfigureClient().Configure, new TConfigureServer().Configure); Client = client; Server = server; }
protected virtual async Task <(IDebugAdapterClient client, IDebugAdapterServer server)> Initialize( Action <DebugAdapterClientOptions> clientOptionsAction, Action <DebugAdapterServerOptions> serverOptionsAction ) { var clientPipe = new Pipe(TestOptions.DefaultPipeOptions); var serverPipe = new Pipe(TestOptions.DefaultPipeOptions); _client = DebugAdapterClient.Create( options => { options .WithLoggerFactory(TestOptions.ClientLoggerFactory) .ConfigureLogging( x => { x.SetMinimumLevel(LogLevel.Trace); x.Services.AddSingleton(TestOptions.ClientLoggerFactory); } ) .Services .AddTransient(typeof(IPipelineBehavior <,>), typeof(SettlePipeline <,>)) .AddSingleton(ClientEvents as IRequestSettler); ConfigureClientInputOutput(serverPipe.Reader, clientPipe.Writer, options); clientOptionsAction(options); } ); _server = DebugAdapterServer.Create( options => { options .WithLoggerFactory(TestOptions.ServerLoggerFactory) .ConfigureLogging( x => { x.SetMinimumLevel(LogLevel.Trace); x.Services.AddSingleton(TestOptions.ServerLoggerFactory); } ) .Services .AddTransient(typeof(IPipelineBehavior <,>), typeof(SettlePipeline <,>)) .AddSingleton(ServerEvents as IRequestSettler); ConfigureServerInputOutput(clientPipe.Reader, serverPipe.Writer, options); serverOptionsAction(options); } ); Disposable.Add(_client); Disposable.Add(_server); return(await Observable.FromAsync(_client.Initialize).ForkJoin( Observable.FromAsync(_server.Initialize), (a, b) => (_client, _server) ).ToTask(CancellationToken)); }
// PSES follows the following flow: // Receive a Initialize request // Run Initialize handler and send response back // Receive a Launch/Attach request // Run Launch/Attach handler and send response back // PSES sends the initialized event at the end of the Launch/Attach handler // The way that the Omnisharp server works is that this OnStarted handler runs after OnInitialized // (after the Initialize DAP response is sent to the client) but before the _Initalized_ DAP event // gets sent to the client. Because of the way PSES handles breakpoints, // we can't send the Initialized event until _after_ we finish the Launch/Attach handler. // The flow above depicts this. To achieve this, we wait until _debugStateService.ServerStarted // is set, which will be done by the Launch/Attach handlers. public async Task OnStarted(IDebugAdapterServer server, CancellationToken cancellationToken) { // We wait for this task to be finished before triggering the initialized message to // be sent to the client. await _debugStateService.ServerStarted.Task.ConfigureAwait(false); }