question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to extend an existing language with an LSP server?

See original GitHub issue

Documentation says:

If there is already a VS supported language service installed (for example, JavaScript), can I still install an LSP language server extension that offers additional features (such as linting)?

Yes, but […]

Can you explain how to do that? I’m precisely trying to provide diagnostics for JavaScript using an LSP server. So I followed the tutorial to create a vsix with a client implementing ILanguageClient. The only difference is that instead of

  [Export(typeof(ILanguageClient))]
  [ContentType("bar")]

I tried:

  [Export(typeof(ILanguageClient))]
  [ContentType("JavaScript")]

But then ActivateAsync is never called.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:13 (11 by maintainers)

github_iconTop GitHub Comments

2reactions
gundermanccommented, Dec 13, 2021

Is with LSP something like this is possible?

Hi @ivanjeremic, something like this is possible, but it may have unexpected implications, such as breaking mixed language scenarios (HTML in Razor, for example), I recommend validating your extension very very carefully.

There are three options for extending a language that already has an in-box language service:

Add another LSP Server

IMPORTANT: this sort of extensibility is not officially supported. Use at your own risk.

You can do this using the existing ILanguageClient sample project. The main change you need to make is to use the content type of the existing language, instead of inventing your own. Start with this project and then:

This should now make it so that your LSP server starts at the same time as the inbox language server or classic language service.

Note that not all features support working with multiple active language servers at the same time. You may have better luck using the in-process extensibility for such additive extensions.

Use in-process extensibility

See the samples in this repo, such as:

The overwhelming majority of these extensibility points can be driven by multiple extensions at the same time. You will likely need to do the same reuse the existing content type trick above.

Replace an Inbox Language Service Entirely

IMPORTANT: this will supersede the language entirely, per @asklar’s ask, is quite involved, and may have unintended side effects.

  • Implement an editor factory (see DemoProject.zip or this VSSDK sample project)
  • Your editor factory must have a higher priority than the language you are trying to supersede and declare the extensions you want (‘idl’) so that you get called before it.
[ProvideEditorExtension(typeof(EditorFactory), ".idl", 42,
              ProjectGuid = "{A2FE74E1-B743-11d0-AE1A-00A0C90FFFC3}",
              TemplateDir = "Templates",
              NameResourceID = 106)]

  • Your editor factory creates a regular VS code window in CreateEditorInstance(), much like Roslyn does in their editor factory. If you run into any issues, you can look at theirs for reference.
  • Your editor factory sets the document’s content type to your custom content type (the one that descends from ‘code-remote-base’. This sets up the editor to open the document with your LSP server instead of C++.
        //******************************************************
        //* TODO: Replace with your LSP content type.
        //******************************************************
        private const string ContentTypeName = "text";

  • Before returning your text view and document, disable automatic language service SID detection, which is the old, rather obscure mechanism by which C++ lights up today. Without this step, Editor auto-detects C++ as the content type for the file by looking at a map in the registry that indicates that IDL is handled by C++ LS.
                // Disable language service auto-detection before loading document data.
                // This prevents the C++ language service content type from being set.
                return userData.SetData(VSConstants.VsTextBufferUserDataGuid.VsBufferDetectLangSID_guid, false);

End to end demo project: DemoProject.zip

2reactions
LukaszMendakiewiczcommented, Jun 17, 2021

Thanks @asklar for a thorough write-up. I’m forwarding this to our Program Managers who can account for it in the feature planning.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Language Server Extension Guide
LSP Languages and Editors. In this guide, we will: Explain how to build a Language Server extension in VS Code using the provided...
Read more >
How can I extend an existing language server?
What I am looking for is to extend javascript language server and provide extra keywords, syntax highlighting, auto complete, etc.
Read more >
Add a Language Server Protocol extension
Learn how to create a Visual Studio extension that integrates a language server based on the Language Server Protocol (LSP).
Read more >
Extending a client with the language server protocol
In this post we will investigate how to use the language server protocol for actually extending any client understanding the LSP.
Read more >
How to "extend" LSP? : r/neovim
I don't know much about extending an existing LS or the protocol specification, but that seems a lot more difficult to do. Upvote...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found