// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamJsonRpc;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Remote;
using Roslyn.Utilities;
using Microsoft.VisualStudio.LanguageServices.Implementation;
namespace Microsoft.VisualStudio.LanguageServices.Remote
{
///
/// Helper type that abstract out JsonRpc communication with extra capability of
/// using raw stream to move over big chunk of data
///
internal class JsonRpcClient : IDisposable
{
private readonly JsonRpc _rpc;
private readonly CancellationToken _cancellationToken;
private JsonRpcDisconnectedEventArgs _debuggingLastDisconnectReason;
private string _debuggingLastDisconnectCallstack;
public JsonRpcClient(
Stream stream, object callbackTarget, bool useThisAsCallback, CancellationToken cancellationToken)
{
Contract.Requires(stream != null);
var target = useThisAsCallback ? this : callbackTarget;
_cancellationToken = cancellationToken;
_rpc = new JsonRpc(new JsonRpcMessageHandler(stream, stream), target);
_rpc.JsonSerializer.Converters.Add(AggregateJsonConverter.Instance);
_rpc.Disconnected += OnDisconnected;
}
public async Task InvokeAsync(string targetName, params object[] arguments)
{
_cancellationToken.ThrowIfCancellationRequested();
try
{
await _rpc.InvokeAsync(targetName, arguments).ConfigureAwait(false);
}
catch (Exception ex) when (ReportUnlessCanceled(ex, _cancellationToken))
{
// any exception can be thrown from StreamJsonRpc if JsonRpc is disposed in the middle of read/write.
// until we move to newly added cancellation support in JsonRpc, we will catch exception and translate to
// cancellation exception here. if any exception is thrown unrelated to cancellation, then we will rethrow
// the exception
_cancellationToken.ThrowIfCancellationRequested();
throw;
}
}
public async Task InvokeAsync(string targetName, params object[] arguments)
{
_cancellationToken.ThrowIfCancellationRequested();
try
{
return await _rpc.InvokeAsync(targetName, arguments).ConfigureAwait(false);
}
catch (Exception ex) when (ReportUnlessCanceled(ex, _cancellationToken))
{
// any exception can be thrown from StreamJsonRpc if JsonRpc is disposed in the middle of read/write.
// until we move to newly added cancellation support in JsonRpc, we will catch exception and translate to
// cancellation exception here. if any exception is thrown unrelated to cancellation, then we will rethrow
// the exception
_cancellationToken.ThrowIfCancellationRequested();
throw;
}
}
public Task InvokeAsync(string targetName, IEnumerable