Language Server Protocol, Java and Emacs

Prologue Link to heading

Lately I keep hearing about “how much software development has changed over the last half of the decade”. This usually refers to the adoption of containers, cloud etc. I would like to focus on an other factor of the change and that is the plethora of development related systems and services.

So its typical for a team to have:

  • version control
  • code review systems
  • code analysis systems
  • project management
  • issue trackers
  • continuous integration
  • chat / messaging

Add email to that and you realize that most of development related tasks now days take place in the browser. Unfortunately, browsers by nature are unaware of the content they serve, so its not trivial to automate your workflow in the browser. So, if the browser is not going to play the role of ‘Swiss army knife’ for development then what?

One could put all hopes in modern IDEs, however IDEs tend to be specialized more on language features and less about integration with external systems and services. The later is usually a space where general purpose editors are better. And that is mostly because the have a wider and more uniform audience. On the other hand these editors are not so rich in language related features.

So a big question is “Will editors like Atom, Emacs or Visual Studio Code ever be competitive to traditional IDEs for writing code?” At least for Java developers, this used to be a “not viable option”.

This is something that is going to change, due to the `Language Server Protocol`.

What is the language server protocol? Link to heading

LSP is a standardized protocol for how “language servers” and “development tools” communicate. A language server implements all the language specific operations once and then different development tools can connect to it and get the functionality for free.

So, if I create a new language say “AwesomeScript”, instead of creating support for all editors out there, I’ll just need to implement the language server once. Then I would just need to write just a little bit of code for each editor (if any at all), to hook to the “language server”.

The history of language servers Link to heading

Traditional editors like Emacs or vim have been using language servers for a while now. Some examples that come to mind are:

There was no standard protocol at that time (though there were visible similarities). The effort of standardization was initiated by Microsoft, as they starting implementing one server after the other for the needs of visual studio code. More details on LSP history.

Language Server Protocol and Java Link to heading

I’ve been writing Java for more than 15 years now. For nearly a decade I’ve been exclusively using Intellij for Java development. For everything else my goto editor has been Emacs (at least the last year or so). So, it made sense for me to experiment with LSP on Emacs and see how far can I get.

Eclipse Java Language Server Link to heading

For Java the most popular implementation of the protocol is Eclipse Java Language Server. At this point I have to clarify that I’ve never managed to productively use the Eclipse IDE. It always felt that it required a lot of manual configuration and tuning for things (e.g. maven support, apt and more) that other alternatives provided out of the box.

The initial experience exceeded my expectations.

  • It was a lot faster than Eclim.
  • Navigating the code was working great.
  • Functionality provided by lsp-ui worked surprisingly well (sideline, doc etc).
  • It gave me access to some simple refactoring tasks(see the image above).

Unfortunately, sooner or later the experience became way too Eclipsy for my taste. What do I mean by that? When added things like annotation processors etc into the mix, I started having issues that my “Google Fu” wasn’t able to overcome in the little time I had … … or I am just not used in the “Eclipse” way of things and didn’t want to put the extra effort … … or a little bit of both?

IntelliJ Language Server Link to heading

Here’s where LSP becomes really interesting…

I recently bumped into a project called Intellij LSP Server, that actually provided an Intellij plugin that exposed the IDEs capabilities through LSP. This made it possible to use it as a drop in replacement of Eclipse Java Language Server. So, I could get all the lsp-ui related stuff for free but with added Intellij coolness.

It was a blast! It provided everything that Eclipse Java Language Server did, but with:

  • way better completion that was in par with Intellij.
  • Better “run project” functionality.

Here’s how completion looks:

And here’s how the lsp-ui stuff work with Intellij LSP Server:

The only downside for this project is that its still in alpha state and in many cases the server dies or blocks for user input.

Here’s an example:

File Cache Conflict Link to heading

When Intellij detects that a file has been externally modified it opens up a pop-up that prompts the user to select if it should reload from disk or use the cached version. When this dialog gets popped all the LSP operations are blocked. As there seems no obvious way to disable it I hacked a little bash script to automatically click the button for me without leaving my editor:

The script searches for a window titled “File Cache Conflict” and when it does, it focuses on it and sends the space key event. This accepts the default suggestion which is “Load from file system”. Finally, it switches back to my editor workspace (As an i3 window manager user, I run Intellij on workspace 4 and Emacs on workspace 2).

Here’s how the script looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash

function get-file-cache-conflict-window {
    xdotool search "File Cache Conflict" 2> /dev/null
}

function return-to-workspace {
    xdotool key --clearmodifiers Super_L+2
}

window=$(get-file-cache-conflict-window)
if [ -n "$window" ]; then
    echo "Switching to window $window."
    xdotool windowactivate --sync $window
    sleep 0.1
    xdotool key --clearmodifiers space
    return-to-workspace
fi

Unfortunately, there are other issues like that, that can leave you wondering why things stopped working, but I hope that they will get resolved soon, as I really like the project.

Honorable Mention: Meghanada Link to heading

Meghanada is not using the LSP so I want get into much details about it. I will just say that it did work pretty well for me and my only complaint is that completion requires improvements. Also, it worth mentioning that the maintainer is on fire and he fixes things really fast.

Debug Protocol Link to heading

I recently found out that in the same spirit there is an effort about a Debug protocol. This is also something really needed if one is to move from a specialized IDE to a general purpose editor.

Closing thoughts Link to heading

I am really excited about LSP. I feel that it will provide additional freedom in tool/workflow selection. Also, I think that it will play a very important role in initiatives like Eclipse Che or other Cloud IDEs.

For now, I am sticking to my IDE, but I will continue to experiment LSP as I truly believe in the potential of fully programmable editors. I intend to write more on this subject and maybe even create a demo.

I am interested in hearing about your setup, your experiences or any suggestion, so please do leave a comment!