/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/LanguageServer/roslyn-language-server/ProcessUtilities.cs
71 строка
3 KB
David Barbet
Implement LSP daemon mode (#84199)
25 июл 2026, 00:26
Не верифицирован
25 июл 2026, 00:26
490f516
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.IO.Pipes; namespace Microsoft.CodeAnalysis.LanguageServer.Client; internal enum StreamCopyCompletion { SourceClosed, SourceException, DestinationException, Cancelled, } internal static class ProcessUtilities { private const int BufferSize = 64 * 1024; /// <summary> /// Copies <paramref name="source"/> to <paramref name="destination"/> byte for byte, flushing after every read so /// forwarded data (LSP messages in stdio transport, or diagnostics) is delivered promptly. Runs on a background /// thread so a blocking console read never stalls the caller. Returns when the source ends, either stream faults, /// or forwarding is cancelled. /// </summary> public static Task ForwardStreamAsync(Stream source, Stream destination, CancellationToken cancellationToken) { // Cancellation belongs to CopyStreamAsync rather than Task.Run. CopyStreamAsync converts expected // cancellation to StreamCopyCompletion.Cancelled, so the forwarding task completes normally. return Task.Run(() => CopyStreamAsync(source, destination, cancellationToken), CancellationToken.None); } public static async Task<StreamCopyCompletion> CopyStreamAsync(Stream source, Stream destination, CancellationToken cancellationToken) { var buffer = new byte[BufferSize]; try { while (true) { int bytesRead; try { bytesRead = await source.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { return StreamCopyCompletion.SourceException; } if (bytesRead == 0) return StreamCopyCompletion.SourceClosed; try { await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); await destination.FlushAsync(cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (ex is IOException or ObjectDisposedException) { return StreamCopyCompletion.DestinationException; } } } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { return StreamCopyCompletion.Cancelled; } } }