-
Notifications
You must be signed in to change notification settings - Fork 13
Description
I'm creating a language server, and used this project to get the demo server & client extension up and running in visual Studio code successfully.
I'm also creating an extension for Visual Studio to reuse the language server, as per the instructions here: https://docs.microsoft.com/en-us/visualstudio/extensibility/adding-an-lsp-extension
In short, it looks like VS doesn't handle all the possible formats of the InitializeResult message.
In the spec, the hoverProvider in the server capabilities can be either boolean or HoverOptions, LanguageServer.Net is passing back a HoverOptions, but it looks like VS will only handle a boolean value at this time.
There are probably other instances of this kind of problem, this is the first I've come across.
Obviously, this is the responsibility of Visual Studio to implement the protocol properly, but in the meantime I can work around it by changing the message to a boolean rather than HoverOption. Is this the sort of thing that you'd like to do or accept a PR for, or shall I keep the changes to myself and wait for proper VS support?
The relevant bit of the log from visual studio:
<entry>
<record>2838</record>
<time>2020/05/22 09:57:46.925</time>
<type>Error</type>
<source>Language Extension</source>
<description>System.InvalidOperationException: Connection could not be established with the client. Client did not return a valid connnection. Client: Language Extension
 at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<InitializeAsync>d__76.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at Microsoft.VisualStudio.Threading.ThreadingTools.<WithCancellationSlow>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<ActivateLanguageClientAsync>d__74.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)</description>
</entry>
<entry>
<record>2839</record>
<time>2020/05/22 09:57:48.190</time>
<type>Error</type>
<source>Language Extension</source>
<description>Newtonsoft.Json.JsonReaderException: Error reading boolean. Unexpected token: StartObject. Path 'hoverProvider'.
 at Newtonsoft.Json.JsonReader.ReadAsBoolean()
 at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
 at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
 at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
 at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType)
 at Newtonsoft.Json.Linq.JToken.ToObject[T]()
 at Microsoft.VisualStudio.LanguageServer.Protocol.VSExtensionConverter`2.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
 at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
 at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
 at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
 at StreamJsonRpc.JsonMessageFormatter.JsonRpcResult.GetResult[T]()
 at StreamJsonRpc.JsonRpc.<InvokeCoreAsync>d__116`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
 at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<InitializeAsync>d__76.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at Microsoft.VisualStudio.Threading.ThreadingTools.<WithCancellationSlow>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 at Microsoft.VisualStudio.LanguageServer.Client.RemoteLanguageClientInstance.<ActivateLanguageClientAsync>d__74.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)</description>
</entry>
And the log of messages sent/received by the server:
2020-05-22 10:57:48.077 > {"id":2,"method":"initialize","params":{"processId":15340,"rootPath":"C:\\LocalCode\\Products.Enforcer\\src\\Tooling\\VSCode","rootUri":"file:///C:/LocalCode/Products.Enforcer/src/Tooling/VSCode","capabilities":{"supportsVisualStudioExtensions":true,"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true},"didChangeConfiguration":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":false},"symbol":{"dynamicRegistration":false},"executeCommand":{"dynamicRegistration":false}},"textDocument":{"synchronization":{"willSave":false,"willSaveWaitUntil":false,"didSave":true,"dynamicRegistration":false},"completion":{"completionItem":{"snippetSupport":false,"commitCharactersSupport":true},"contextSupport":false,"dynamicRegistration":false},"hover":{"contentFormat":["plaintext"],"dynamicRegistration":false},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext"],"parameterInformation":{"labelOffsetSupport":true}},"contextSupport":true,"dynamicRegistration":false},"references":{"dynamicRegistration":false},"documentHighlight":{"dynamicRegistration":false},"documentSymbol":{"dynamicRegistration":false},"formatting":{"dynamicRegistration":false},"rangeFormatting":{"dynamicRegistration":false},"onTypeFormatting":{"dynamicRegistration":false},"definition":{"dynamicRegistration":false},"implementation":{"dynamicRegistration":false},"typeDefinition":{"dynamicRegistration":false},"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"dynamicRegistration":false},"codeLens":{"dynamicRegistration":false},"documentLink":{"dynamicRegistration":false},"rename":{"dynamicRegistration":false},"foldingRange":{"lineFoldingOnly":false,"dynamicRegistration":false},"publishDiagnostics":{"tagSupport":true}}},"trace":"off"},"jsonrpc":"2.0"}
2020-05-22 10:57:48.164 < {"id":2,"result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"willSave":true,"willSaveWaitUntil":false,"save":null},"hoverProvider":{"workDoneProgress":false},"completionProvider":{"resolveProvider":true,"triggerCharacters":".","workDoneProgress":false},"signatureHelpProvider":{"triggerCharacters":"()","workDoneProgress":false}}},"jsonrpc":"2.0"}
2020-05-22 10:57:48.329 > {"id":3,"method":"shutdown","jsonrpc":"2.0"}
2020-05-22 10:57:48.330 < {"id":3,"result":null,"jsonrpc":"2.0"}
2020-05-22 10:57:48.337 > {"method":"exit","jsonrpc":"2.0"}
2020-05-22 10:57:48.338 <
Exited