public async Task InitializeAsync() { var factory = new LoggerFactory(); _psesProcess = new PsesStdioProcess(factory, IsDebugAdapterTests); await _psesProcess.Start().ConfigureAwait(false); Console.WriteLine("PowerShell Editor Services Server started with PID {0}", ProcessId); // TIP: Add Breakpoint here and attach debugger using the PID from the above message Diagnostics = new List <Diagnostic>(); TelemetryEvents = new List <PsesTelemetryEvent>(); DirectoryInfo testdir = Directory.CreateDirectory(Path.Combine(s_binDir, Path.GetRandomFileName())); PsesLanguageClient = LanguageClient.PreInit(options => { options .WithInput(_psesProcess.OutputStream) .WithOutput(_psesProcess.InputStream) .WithRootUri(DocumentUri.FromFileSystemPath(testdir.FullName)) .OnPublishDiagnostics(diagnosticParams => Diagnostics.AddRange(diagnosticParams.Diagnostics.Where(d => d != null))) .OnLogMessage(logMessageParams => Output?.WriteLine($"{logMessageParams.Type.ToString()}: {logMessageParams.Message}")) .OnTelemetryEvent(telemetryEventParams => TelemetryEvents.Add( new PsesTelemetryEvent { EventName = (string)telemetryEventParams.ExtensionData["eventName"], Data = telemetryEventParams.ExtensionData["data"] as JObject })); // Enable all capabilities this this is for testing. // This will be a built in feature of the Omnisharp client at some point. var capabilityTypes = typeof(ICapability).Assembly.GetExportedTypes() .Where(z => typeof(ICapability).IsAssignableFrom(z) && z.IsClass && !z.IsAbstract); foreach (Type capabilityType in capabilityTypes) { options.WithCapability(Activator.CreateInstance(capabilityType, Array.Empty <object>()) as ICapability); } }); await PsesLanguageClient.Initialize(CancellationToken.None).ConfigureAwait(false); // Make sure Script Analysis is enabled because we'll need it in the tests. // This also makes sure the configuration is set to default values. PsesLanguageClient.Workspace.DidChangeConfiguration( new DidChangeConfigurationParams { Settings = JToken.FromObject(new LanguageServerSettingsWrapper { Files = new EditorFileSettings(), Search = new EditorSearchSettings(), Powershell = new LanguageServerSettings() }) }); }
public async Task InitializeAsync() { var factory = new LoggerFactory(); _psesProcess = new PsesStdioProcess(factory, true); await _psesProcess.Start().ConfigureAwait(false); var initialized = new TaskCompletionSource <bool>(); PsesDebugAdapterClient = DebugAdapterClient.Create(options => { options .WithInput(_psesProcess.OutputStream) .WithOutput(_psesProcess.InputStream) // The OnStarted delegate gets run when we receive the _Initialized_ event from the server: // https://microsoft.github.io/debug-adapter-protocol/specification#Events_Initialized .OnStarted((client, token) => { Started.SetResult(true); return(Task.CompletedTask); }) // The OnInitialized delegate gets run when we first receive the _Initialize_ response: // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize .OnInitialized((client, request, response, token) => { initialized.SetResult(true); return(Task.CompletedTask); }); }); // 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 client works is that this Initialize method doesn't return until // after OnStarted is run... which only happens when Initialized is received from the server. // so if we would await this task, it would deadlock. // To get around this, we run the Initialize() without await but use a `TaskCompletionSource<bool>` // that gets completed when we receive the response to Initialize // This tells us that we are ready to send messages to PSES... but are not stuck waiting for // Initialized. PsesDebugAdapterClient.Initialize(CancellationToken.None).ConfigureAwait(false); await initialized.Task.ConfigureAwait(false); }