microsoft / VSExtensibility

A repo for upcoming changes to extensibility in Visual Studio, the new extensibility model, and language server protocol.
MIT License
367 stars 46 forks source link

Please provide an LSP client sample #214

Open kaby76 opened 1 year ago

kaby76 commented 1 year ago

I wrote an LSP server and a VS2019 extension that used ILanguageClient to interact with the LSP client that VS2019 implemented. It was modeled after a VSSDK sample. My extension didn't work well for many reasons, but mainly because the LSP client in VS2019 lacked native support for semantic highlighting. I see now Microsoft.VisualStudio.LanguageServer.Server now, finally, contains many of the types that were missing years ago. I want to try to get my server to work with this new extension model, but there's no starting point to work from.

Please provide an example extension in the Samples/ directory that demonstrates how to attach a server to the new client interface in this new out-of-process extension model.

maiak commented 1 year ago

Thanks @kaby76! For your specific use case, I want to make sure I'm understanding the scenario. Could you please clarify whether you're trying to get an LSP server working with an extension in general? Or do you have one working with VSSDK and are trying to get it working with VisualStudio.Extensibility (our new extension model)?

For VisualStudio.Extensibility, we know that compatibility with LSP is very important, so we're currently working on adding LSP support for future releases. Some components like the ILanguageClient type are currently available, but we're still designing the end-to-end experience. Once the whole experience is ready to share and announce, we'll have docs and samples to make sure it's easy to use.

kaby76 commented 1 year ago

Sounds fair. I'll be looking forward to seeing what you produce.

I have an extension that uses VSSDK that packages my own LSP server, all written in C#. The server works with both VSCode and VS2022 17.6.0 preview 2. (I also have a VSCode extension.) The server itself uses Antlr to parse any language and XPath expressions to extract symbol table entries to support LSP services.

The VS2022 extension uses ILanguageClient, and implements public async Task<Connection> ActivateAsync(CancellationToken token). That method starts the server .exe using Process.Start() and returns a new Connection containing the process.StandardInput.BaseStream and process.StandardOutput.BaseStream from the start. The other half of the extension uses IVsTextViewCreationListener, implementing public void VsTextViewCreated(IVsTextView textViewAdapter). That method gets the IWpfTextView, corresponding ITextBuffer, and sets the content type (IContentType) of the buffer that the extension supports if and only if the file extension (e.g., .java) is one of the supported types.

The extension is packaged as a .vsix, which is what https://marketplace.visualstudio.com/ expects in order to be published on the website. That means the packaging details are scattered between a .vsixmanifest (<Identity>, <DisplayName>, <Description>, etc.), but also in the .csproj (<GeneratePkgDefFile>, <IncludeAssemblyInVSIXContainer>, <IncludeDebugSymbolsInVSIXContainer>, etc.).

That, in a nutshell, is the architecture of the extension.

I was also wonder how the new extension is packaged for publication.

olegtk commented 1 year ago

@kaby76, can you please clarify what are you trying to achieve by changing text buffer content type dynamically via IVsTextViewCreationListener ? Are you enabling LSP support for some file extensions your extension doesn't really own but want to augment editing experience for, like .cs? Thanks!

kaby76 commented 1 year ago

@kaby76, can you please clarify what are you trying to achieve by changing text buffer content type dynamically via IVsTextViewCreationListener ? Are you enabling LSP support for some file extensions your extension doesn't really own but want to augment editing experience for, like .cs? Thanks!

Yes. That is exactly what it does. The code for public void VsTextViewCreated(IVsTextView textViewAdapter) associates the buffer with the extension buffer.ChangeContentType(new_content_type, null);. I don't want to hardwire file associations into the extension, e.g., here and here. There may be a better way to apply the extension to that specific file through the UI, but VSIDE didn't seem to have anything several years ago. In VSCode, there is a control on the lower-right border that pops up a table to associate the file with an extension.

olegtk commented 1 year ago

Thanks. What is the new_content_type your extension sets?

kaby76 commented 1 year ago

Thanks. What is the new_content_type your extension sets?

It's found by IContentType new_content_type = content_types.Find(ct => ct.TypeName == "Antlr");, which is statically declared using those MEF declarations. Not only do I still not understand these declarations, but they were hell to write: If anything was off, nothing would work, and there wouldn't be any output as to why the MEF system wasn't working with my extension.

olegtk commented 1 year ago

Yeah, MEF is known for poor diagnosability unfortunately. But the fact that you are able to get Antlr content type at run time means its MEF declaration was accepted. Perhaps it's the mapping to file extension that has issues (FileExtensionToContentTypeDefinition).

anaypaul commented 3 days ago

@kaby76 Please can you share some examples where we are passing initializationOptions and ClientInfo when implementing iLanguageClient?