Using Language Servers to edit code in the Eclipse IDE
Writing in Java but your PHP support has bugs? Eclipse Language Server Protocols are here to help. Learn how the Eclipse IDE is able to consume language servers to provide rich editor features and interact with them without having to learn anything new. In this article, Mickael Istria explains how to make things simpler for developers while keeping things the same for end users with Eclipse LSP4E.
Now, you’re well aware about the benefits of the Language Server Protocol (LSP) to ship reusable edition smartness for your language, and of how LSP4J allows to very easily interact with Language Servers in Java, you probably figured out that the next natural step for the Eclipse Community has been to make the Eclipse IDE able to consume language servers in order to provide typical rich editor features (Completion, Hover, Outline, Problems/Markers, Quick-fixes…) and interact with them from the Eclipse IDE as usual, without having to learn anything new as a user. This is the purpose of the Eclipse LSP4E project, which already covers most of the features of language servers and already shows a nice list of adopters.
For end-users: nothing changes
End-users shouldn’t have to do anything different to work with language servers. Whether a language support tool uses a language server or not is a blackbox to them, they simply have to install language support as they usually do from Marketplace or anywhere else. Then, just open an Eclipse editor for their file and the LSP features are automatically enabled and bound to the typical shortcuts, commands, views… that have been used successfully for a while by JDT, CDT, PDT and most Eclipse editors.
The language support would typically associate Eclipse Platform’s generic editor (which is extended with features coming from LSP4E and Language Server) with the right files. If the association is missing and you find another editor is associated, you’re still free to use the Generic Editor from the
Open With contextual menu to take advantage of all LSP4E features, and to associate the Generic Editor with some filetype.
End-users are given the ability to add a Language Server and to connect to it dynamically via Preferences if they need or want to. But it’s not the main user-story so we’ll skip it as part of this article and invite anyone interested to come and ask on the LSP4E mailing-list.
For Eclipse plugins or Language Servers developers: an extension point, a basic interface to implement, and packaging
Plugin developers willing to add editing features for a given language should consider the adoption of Language Servers as one of the best options. One of the reasons being that Language Servers are reusable across various editors and help the language to easily reach a diverse set of clients. So first things first, plugin developers interested in language support should get familiar with the protocol and if applicable, should consider implementing this protocol for their language (using LSP4J for instance).
As this is more a topic general to the Language Server Protocol and LSP4J, I’ll let you refer to those articles in order to create your language server; and I’ll only focus on how to bind an existing Language Server into the Eclipse IDE here.
The most efficient approach so far consists of using the Eclipse Platform’s Generic Editor for your files, to which LSP4E is already contributing; and then to define how to start/connect to the language server, and finally to bind the language server declaration to the target content-types.
Let’s have a more detailed look into this using the aCute example, which brings C# edition into Eclipse IDE.
First, the plugin does define as extension in plugin.xml a content-type for the target files and associate this content-type with the Generic Editor:
Then, the plugin defines a Language Server and associates it with the content-type:
The Language Server we use for C# is OmniSharp, hence the names in plugin.xml. From there, the only missing piece is to implement “org.eclipse.acute.OmnisharpStreamConnectionProvider”. This class is the one responsible for providing an input and an output stream to chat with the language server (as it’s a request/response/notification communication pattern). In this case, the decision was to have the class also startup the language server, but some other stories may simply connect to a server that is already running. The of the server lifecycle is up to the adopter according to the specificities of the language server.
This simply runs a command like
/usr/bin/node /path/to/omnisharp/server/languageserver.js from inside the IDE and connect to the streams of this process to send requests and notifications conforming to LSP specification. LSP4E takes care of everything else, so with this ~100 lines of simple code, you have rich editior support for C# in Eclipse IDE!
As defining the connection of Eclipse IDE to the Language Servers is almost trivial, more care should be taken by the plugin developers on how to package the Language Server. This is indeed an important and tricky question and the answer strongly depend on the Language Server: for some which are available a CLI and part of some official SDK you expect your users to be using, you can simply reference the CLI; for some others who are not distributed as CLI tool, you may have to embed them in some bundle (it’s the case for the example above), some language servers may be remote and can use streams over TCP or WebSocket… There is not one which is strongly better than the other, and the choice depends almost solely on how the Language Server is distributed.
Current adopters and success stories
LSP4E and the Language Server architecture are already adopted by a few projects, some of which already deliver a better user experience than traditional Eclipse editors.Here is the list of Eclipse IDE plugins providing editors using LSP4E:
- aCute: C# development with OmniSharp Language Server
- Lsp4e-php: PHP editing with Soucegraph’s PHP Language Server with contributions from Zend, who implement Lsp4e-php.
- Fabric8 dependency analysis: adds edition assist in pom.xml and package.json to prevent using versions with known security issues, using Fabric8 dependency analysis Language Server and OpenShift.io
- Your project? If so come to share it with us on the LSP4E mailing-list!
Note: most of the examples above do rely on TextMate grammars and Eclipse TM4E for syntax highlighting, since the Language Server Protocol doesn’t include support for syntax highlighting.
All the layers of this architecture (Eclipse Platform, LSP4J, LSP4E…) and all examples (including the language servers) listed here are open source and welcome contributions. Here is a good entry-point to start contributing to LSP4E. We can’t wait to review your patches!
I’ll be presenting all that in greater detail at EclipseCon France in Toulouse at the end of June. Join me to have a chat about LSP!
This post was originally published in the May 2017 issue of the Eclipse Newsletter: Language Server Protocol
For more information and articles check out the Eclipse Newsletter.