I call a language server from an extension for VS2022. This was created using Omnisharp.Extensions.LanguageServer 0.19.9. For the call I use the (currently) experimental class LanguageServerProvider from Microsoft.VisualStudio.Extensibility 17.10.2084.
When starting my languageserver from my extension I get an exception from "VS/IDE/TaskStatusCenter/RunningRegisteredTaskFailed":
StreamJsonRpc.RemoteMethodNotFoundException: No method by the name 'initialize' is found.
at StreamJsonRpc.JsonRpc.<InvokeCoreAsync>d__154`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.LanguageServer.Client.JsonRpcExtensionMethods.<SendMethodRequestWithTelemetryAsync>d__0`2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<SendInitializeRequestAsync>d__115.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<InitializeAsync>d__110.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Threading.TplExtensions.<WithTimeout>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<TrackTaskAsync>d__113.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<ActivateLanguageClientAsync>d__122.MoveNext()
What does this message mean? For which class is the "initialize" method missing?
I use
Here is my language-server-provider:
using System.Diagnostics;
using System.IO.Pipelines;
using JetBrains.Annotations;
using Microsoft.VisualStudio.Extensibility;
using Microsoft.VisualStudio.Extensibility.LanguageServer;
using Microsoft.VisualStudio.RpcContracts.LanguageServerProvider;
using Nerdbank.Streams;
using ReniLSP;
namespace Reni.LSPVSIX;
#pragma warning disable VSEXTPREVIEW_LSP
[VisualStudioContribution]
[UsedImplicitly]
public sealed class ReniLanguageServerProvider : LanguageServerProvider
{
[UsedImplicitly]
Task? ServerPipeTask;
public ReniLanguageServerProvider
(ExtensionCore container, VisualStudioExtensibility extensibilityObject, TraceSource traceSource)
: base(container, extensibilityObject) { }
public override LanguageServerProviderConfiguration LanguageServerProviderConfiguration =>
new("Reni Language Server",
new[]
{
DocumentFilter.FromDocumentType(Constants.LanguageName),
});
// Activate the language server and return a duplex pipe that communicates with the server.
public override Task<IDuplexPipe?> CreateServerConnectionAsync(CancellationToken token)
{
var (pipeToServer, pipeToVS) = FullDuplexStream.CreatePair();
ServerPipeTask = Task.Run(
() => MainContainer.RunServer(pipeToVS.UsePipeReader(), pipeToServer.UsePipeWriter())
, token
);
return Task.FromResult<IDuplexPipe?>(new DuplexPipe(pipeToServer.UsePipeReader(), pipeToVS.UsePipeWriter()));
}
protected override void Dispose(bool isDisposing)
{
if(isDisposing)
ServerPipeTask?.Dispose();
base.Dispose(isDisposing);
}
public override Task OnServerInitializationResultAsync
(
ServerInitializationResult startState, LanguageServerInitializationFailureInfo? initializationFailureInfo
, CancellationToken cancellationToken
) =>
// Method called when server activation was completed successfully or failed, denoted by "startState".
Task.CompletedTask;
}
The method CreateServerConnectionAsync was wrong. This is working:
public override Task<IDuplexPipe?> CreateServerConnectionAsync(CancellationToken token)
{
var (pipeToLSP, pipeToVS) = FullDuplexStream.CreatePair();
ServerPipeTask = Task.Run(() => MainContainer.RunServer(pipeToLSP.UsePipeReader(), pipeToLSP.UsePipeWriter()), token);
var duplexPipe = new DuplexPipe(pipeToVS.UsePipeReader(), pipeToVS.UsePipeWriter());
return Task.FromResult<IDuplexPipe?>(duplexPipe);
}