resharper/src/ProjectModel/GodotMessagingClient.cs (108 lines of code) (raw):
using System;
using System.Threading.Tasks;
using GodotTools.IdeMessaging;
using GodotTools.IdeMessaging.Requests;
using JetBrains.Application.Parts;
using JetBrains.Application.Threading;
using JetBrains.Collections.Viewable;
using JetBrains.Lifetimes;
using JetBrains.ProjectModel;
using JetBrains.Rd.Base;
using JetBrains.ReSharper.Feature.Services.Protocol;
using JetBrains.Rider.Model.Godot.FrontendBackend;
using JetBrains.Util;
using ILogger = JetBrains.Util.ILogger;
namespace JetBrains.ReSharper.Plugins.Godot.ProjectModel
{
[SolutionComponent(InstantiationEx.LegacyDefault)]
public class GodotMessagingClient : IMessageHandler, GodotTools.IdeMessaging.ILogger
{
private const string Identity = "Rider";
private readonly ILogger myLogger;
private Client myClient;
public GodotMessagingClient(ISolution solution, ILogger logger, Lifetime lifetime, IThreading threading)
{
myLogger = logger;
var model = solution.GetProtocolSolution().GetGodotFrontendBackendModel();
model.GodotDescriptor.AdviseOnce(lifetime, descriptor =>
{
if (descriptor.IsPureGdScriptProject) return;
myClient = new Client(Identity, descriptor.MainProjectBasePath, this, this);
SubscribeConnected(logger, threading, model, myClient);
SubscribeDisconnected(logger, threading, model, myClient);
myClient.Start();
lifetime.OnTermination(() =>
{
myClient.Dispose();
});
});
}
private void SubscribeDisconnected(ILogger logger, IThreading threading, GodotFrontendBackendModel model,
Client client)
{
client.AwaitDisconnected().ContinueWith(_ =>
{
logger.Info("Godot Editor disconnected...");
model.EditorState.SetValue(GodotEditorState.Disconnected);
SubscribeDisconnected(logger, threading, model, client);
}, threading.Tasks.GuardedMainThreadScheduler);
}
private void SubscribeConnected(ILogger logger, IThreading threading, GodotFrontendBackendModel model,
Client client)
{
client.AwaitConnected().ContinueWith(_ =>
{
logger.Info("Godot Editor connected...");
model.EditorState.SetValue(GodotEditorState.Connected);
SubscribeConnected(logger, threading, model, client);
}, threading.Tasks.GuardedMainThreadScheduler);
}
public Task<MessageContent> HandleRequest(Peer peer, string id, MessageContent content,
GodotTools.IdeMessaging.ILogger logger)
{
// TODO: unsure what this is for. Maybe PlayRequests?
throw new NotImplementedException("Not implemented yet!");
}
public async Task<CodeCompletionResponse> SendNodePathRequest(string fullPath)
{
var response = await myClient.SendRequest<CodeCompletionResponse>(new CodeCompletionRequest
{
Kind = CodeCompletionRequest.CompletionKind.NodePaths,
ScriptFile = fullPath
});
return response;
}
public async Task<CodeCompletionResponse> SendInputActionsRequest(string fullPath)
{
var response = await myClient.SendRequest<CodeCompletionResponse>(new CodeCompletionRequest()
{
Kind = CodeCompletionRequest.CompletionKind.InputActions,
ScriptFile = fullPath
});
return response;
}
public void LogDebug(string message)
{
myLogger.Verbose(message);
}
public void LogInfo(string message)
{
myLogger.Info(message);
}
public void LogWarning(string message)
{
myLogger.Warn(message);
}
public void LogError(string message)
{
// GodotTools.IdeMessaging.Client logs errors, which are not always errors like in `ConnectToServer`
myLogger.Warn(message);
}
public void LogError(string message, Exception e)
{
myLogger.Error(message, e);
}
public bool IsReady()
{
return myClient != null;
}
}
}