/// <summary> /// Register a handler for empty notifications. /// </summary> /// <param name="languageClient"> /// The <see cref="LanguageClient"/>. /// </param> /// <param name="method"> /// The name of the notification method to handle. /// </param> /// <param name="handler"> /// A JSON-RPC <see cref="INotificationHandler"/> that implements the handler. /// </param> /// <returns> /// An <see cref="IDisposable"/> representing the registration. /// </returns> public static IDisposable HandleEmptyNotification(this LanguageClient languageClient, string method, INotificationHandler handler) { if (languageClient == null) { throw new ArgumentNullException(nameof(languageClient)); } if (String.IsNullOrWhiteSpace(method)) { throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(method)}.", nameof(method)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } return(languageClient.RegisterHandler( new JsonRpcEmptyNotificationHandler(method, handler) )); }
/// <summary> /// Register a handler for requests. /// </summary> /// <typeparam name="TRequest"> /// The request message type. /// </typeparam> /// <typeparam name="TResponse"> /// The response message type. /// </typeparam> /// <param name="languageClient"> /// The <see cref="LanguageClient"/>. /// </param> /// <param name="method"> /// The name of the request method to handle. /// </param> /// <param name="handler"> /// A <see cref="RequestHandler{TRequest}"/> delegate that implements the handler. /// </param> /// <returns> /// An <see cref="IDisposable"/> representing the registration. /// </returns> public static IDisposable HandleRequest <TRequest, TResponse>(this LanguageClient languageClient, string method, RequestHandler <TRequest, TResponse> handler) { if (languageClient == null) { throw new ArgumentNullException(nameof(languageClient)); } if (String.IsNullOrWhiteSpace(method)) { throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(method)}.", nameof(method)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } return(languageClient.RegisterHandler( new DelegateRequestResponseHandler <TRequest, TResponse>(method, handler) )); }
/// <summary> /// Run a language client over the specified streams. /// </summary> /// <param name="serverProcess"> /// The <see cref="NamedPipeServerProcess"/> used to wire up the client and server streams. /// </param> /// <returns> /// A <see cref="Task"/> representing the operation. /// </returns> static async Task RunLanguageClient(NamedPipeServerProcess serverProcess) { if (serverProcess == null) { throw new ArgumentNullException(nameof(serverProcess)); } Log.Information("Starting client..."); LanguageClient client = new LanguageClient(Log.Logger, serverProcess) { ClientCapabilities = { Workspace = { DidChangeConfiguration = new DidChangeConfigurationCapability { DynamicRegistration = false } } } }; using (client) { // Listen for log messages from the language server. client.Window.OnLogMessage((message, messageType) => { Log.Information("Language server says: [{MessageType:l}] {Message}", messageType, message); }); // Listen for our custom notification from the language server. client.HandleNotification <DummyParams>("dummy/notify", notification => { Log.Information("Received dummy notification from language server: {Message}", notification.Message ); }); JObject settings = new JObject( new JProperty("setting1", true), new JProperty("setting2", "Hello") ); await client.Initialize( workspaceRoot : @"C:\Foo", initializationOptions : settings ); Log.Information("Client started."); // Update server configuration. client.Workspace.DidChangeConfiguration(settings); // Invoke our custom handler. await client.SendRequest("dummy", new DummyParams { Message = "Hello, world!" }); Log.Information("Shutting down language client..."); await client.Shutdown(); Log.Information("Language client has shut down."); } }