New in Eclipse JDT Language Server

It's been "almost" a year since our last article for the Eclipse Newsletter, and a lot has happened in the jdt.ls project since. In this article, we'll cover some of the highlights of the past releases and the impact the project had on the Java ecosystem.

Improvements all over the place!

Over the past 10 months, jdt.ls received a fair share of bug fixes and some notable improvements, including, among other things:

  • smaller distribution size,
  • faster start times,
  • improved diagnostics performance,
  • new Java 9 support,
  • improvements to the "organize imports" refactoring (with favorite imports, imports order, execute on save),
  • code actions galore (known as quick-fixes in Eclipse IDE land),
  • the ability to disable autobuilds, or trigger incremental or full builds on demand,
  • proper test classpath isolation (i.e. test classes don't leak into main code anymore),
  • improved symbol (a.k.a. Type) search,
  • new multi-root support,
  • partial rename refactoring support (still missing file rename)
  • support for 3rd party extensions (debugger, decompilers, new commands),

For some of those fixes and improvements, jdt.ls leverages the latest milestone developments from the Eclipse Photon SDK.

jdt.ls integrated everywhere

While vscode-java is the reference implementation for jdt.ls clients, others have jumped on the jdt.ls train, like the ide-java extension for the Atom editor:

Atom with ide-java extension

or YCMD, providing autocompletion in VIM:

A flourishing ecosystem

As we're seeing jdt.ls being used more and more across the LSP client landscape, we've inevitably received many requests to allow 3rd party extensions to integrate deeply with jdt.ls.

Because the server is based on the OSGi framework powering the Eclipse IDE, we could open the gates to allow external extensions, fairly easily. During the initialize request, clients must provide the bundles parameter, which lists the full path of all OSGi bundles needed to be started by jdt.ls :

interface InitializationOptions {
        /**
         * a list of Java LS extensions
         */
        bundles?: string[];
        /**
         * a list of workspace folders
         */
        workspaceFolders?: WorkspaceFolder[];
        /**
         * Java LS configuration settings
         */
        settings?: JavaConfigurationSettings[];
}

In order to contribute commands, bundles need to provide a extension point org.eclipse.jdt.ls.core.delegateCommandHandler in their plugin.xml, with a list of command ids, like :

<plugin>
   <extension point="org.eclipse.jdt.ls.core.delegateCommandHandler">
      <delegateCommandHandler class="com.microsoft.java.debug.plugin.internal.JavaDebugDelegateCommandHandler">
            <command id="vscode.java.startDebugSession"/>
            <command id="vscode.java.resolveClasspath"/>
            <command id="vscode.java.resolveMainClass"/>
            <command id="vscode.java.buildWorkspace"/>
            <command id="vscode.java.fetchUsageData"/>
            <command id="vscode.java.updateDebugSettings"/>
       </delegateCommandHandler>
   </extension>
</plugin>

This mechanism allowed the Microsoft team to implement a complete Java debugger extension for VS Code:

VS Code Java debugger in action

... and a Java Test runner

VS Code Java Test Runner

Eclipse Che, currently in the process of replacing its own Java language server with jdt.ls, should reach feature parity with its old server by providing custom jdt.ls extensions, for instance dependency visualization:


David Gileadi added support for external decompilers implementations by implementing the org.eclipse.jdt.ls.core.contentProvider extension point. A VSCode extension is available, but the bundles can be embedded in any client.

Finally, Gorkem Ercan, fearless leader of the jdt.ls project, can satisfy his dogfooding needs by developing jdt.ls with jdt.ls in VS Code: his vscode-pde extension allows the development of Eclipse Plugins by loading a target platform file, referenced in a javaConfig.json file. The org.eclipse.jdt.ls.core.importers extension point allows 3rd party adopters to expand the types of projects imported by jdt.ls beyond simply Maven, Gradle and Eclipse projects.

What's next?

The jdt.ls team tries to keep a 2-weeks release cadence, making each release incrementally superior to the last. We're collaborating with the LSP4J and the Microsoft teams to keep improving the Language Server Protocol, so, in the near future, we'll hopefully be able to provide :

  • full renaming support (including moving files),
  • more refactorings / code actions
  • textDocument/onTypeFormatting support, to automatically format your code after typing ; or when going to the next line,
  • provide a progress report API, allowing clients to track background activity
  • provide a notification API to broadcast classpath changes
  • Java 10 support
  • squash more bugs

All contributions are welcome, so feel free to chime in the eclipse.jdt.ls channel on Mattermost, or open bug reports (and submit pull requests!) to https://github.com/eclipse/eclipse.jdt.ls

About the Author