[gnome-builder/wip/albfan/java-langserver] java-langserv: LSP integration for Java
- From: Alberto Fanjul <albfan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/albfan/java-langserver] java-langserv: LSP integration for Java
- Date: Tue, 16 Apr 2019 06:01:21 +0000 (UTC)
commit 69049e503cc44ab6b5ab02beede027bb8bedc09c
Author: Alberto Fanjul <albertofanjul gmail com>
Date: Fri Apr 12 12:03:03 2019 +0200
java-langserv: LSP integration for Java
Basic integration with ls running from host
meson_options.txt | 1 +
src/plugins/java-langserv/README.md | 37 +++++
src/plugins/java-langserv/java-langserv.plugin | 9 ++
.../java-langserv/java_langserver_plugin.py | 155 +++++++++++++++++++++
src/plugins/java-langserv/meson.build | 13 ++
src/plugins/meson.build | 2 +
6 files changed, 217 insertions(+)
---
diff --git a/meson_options.txt b/meson_options.txt
index 57fe9301c..74be15e41 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -46,6 +46,7 @@ option('plugin_gradle', type: 'boolean')
option('plugin_grep', type: 'boolean')
option('plugin_html_completion', type: 'boolean')
option('plugin_html_preview', type: 'boolean')
+option('plugin_java_langserv', type: 'boolean')
option('plugin_jedi', type: 'boolean')
option('plugin_jhbuild', type: 'boolean')
option('plugin_make', type: 'boolean')
diff --git a/src/plugins/java-langserv/README.md b/src/plugins/java-langserv/README.md
new file mode 100644
index 000000000..5c2d23670
--- /dev/null
+++ b/src/plugins/java-langserv/README.md
@@ -0,0 +1,37 @@
+# language server client for java
+
+Wrap [java-language-server](https://github.com/georgewfraser/java-language-server).
+
+## Installing and testing
+
+1. Install `java-language-server`
+
+```
+git clone https://github.com/georgewfraser/java-language-server
+cd java-language-server
+JAVA_HOME=/path/to/jdk11 scripts/link_mac.sh
+```
+
+2. Set up your environment
+
+Create a launcher in /usr/bin
+
+```
+$ cat > /usr/bin/javals <<EOF
+#!/bin/bash
+
+/path/to/java-language-server/dist/mac/bin/launcher $@
+```
+
+Alternatively create a script in a custom path with `JAVALS_CMD` env:
+
+```
+export JAVALS_CMD="/custom/path/to/javals-script"
+```
+
+3. Launch Builder, open a java project
+4. Right click on a method and click 'go to definition'
+
+## Bugs:
+
+Please report on IRC or gitlab
diff --git a/src/plugins/java-langserv/java-langserv.plugin b/src/plugins/java-langserv/java-langserv.plugin
new file mode 100644
index 000000000..5694d4f6a
--- /dev/null
+++ b/src/plugins/java-langserv/java-langserv.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Builtin=true
+Copyright=Copyright © 2019 Alberto Fanjul
+Description=Provides LSP integration for java
+Loader=python3
+Module=java_langserver_plugin
+Name=Java Language Server Plugin
+X-Builder-ABI=@PACKAGE_ABI@
+X-Symbol-Resolver-Languages=java
diff --git a/src/plugins/java-langserv/java_langserver_plugin.py
b/src/plugins/java-langserv/java_langserver_plugin.py
new file mode 100755
index 000000000..0dbb86e6d
--- /dev/null
+++ b/src/plugins/java-langserv/java_langserver_plugin.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python3
+
+# java_langserv_plugin.py
+#
+# Copyright 2019 Alberto Fanjul <albertofanjul gmail com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This plugin provides integration with the Java Language Server.
+It builds off the generic language service components in libide
+by bridging them to our supervised Java Language Server.
+"""
+
+import os
+import gi
+
+from gi.repository import GLib
+from gi.repository import Gio
+from gi.repository import GObject
+from gi.repository import Ide
+
+DEV_MODE = os.getenv('DEV_MODE') and True or False
+
+class JavaService(Ide.Object):
+ _client = None
+ _has_started = False
+ _supervisor = None
+
+ @classmethod
+ def from_context(klass, context):
+ return context.ensure_child_typed(JavaService)
+
+ @GObject.Property(type=Ide.LspClient)
+ def client(self):
+ return self._client
+
+ @client.setter
+ def client(self, value):
+ self._client = value
+ self.notify('client')
+
+ def do_stop(self):
+ if self._supervisor:
+ supervisor, self._supervisor = self._supervisor, None
+ supervisor.stop()
+
+ def _which_java_lanserver(self):
+ path = os.getenv('JAVALS_CMD')
+ if path and os.path.exists(os.path.expanduser(path)):
+ return path
+ return "javals"
+
+ def _ensure_started(self):
+ # To avoid starting the process unconditionally at startup, lazily
+ # start it when the first provider tries to bind a client to its
+ # :client property.
+ if not self._has_started:
+ self._has_started = True
+
+ launcher = self._create_launcher()
+ launcher.set_clear_env(False)
+
+ # Locate the directory of the project and run java-langserver from there
+ workdir = self.get_context().ref_workdir()
+ launcher.set_cwd(workdir.get_path())
+
+ launcher.push_argv('%s %s' % (self._which_java_lanserver(),
+ "--quiet" if not DEV_MODE else ""))
+
+ # Spawn our peer process and monitor it for
+ # crashes. We may need to restart it occasionally.
+ self._supervisor = Ide.SubprocessSupervisor()
+ self._supervisor.connect('spawned', self._ls_spawned)
+ self._supervisor.set_launcher(launcher)
+ self._supervisor.start()
+
+ def _ls_spawned(self, supervisor, subprocess):
+ stdin = subprocess.get_stdin_pipe()
+ stdout = subprocess.get_stdout_pipe()
+ io_stream = Gio.SimpleIOStream.new(stdout, stdin)
+
+ if self._client:
+ self._client.stop()
+ self._client.destroy()
+
+ self._client = Ide.LspClient.new(io_stream)
+ self.append(self._client)
+ self._client.add_language('java')
+ self._client.start()
+ self.notify('client')
+
+ def _create_launcher(self):
+ flags = Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE
+ if not DEV_MODE:
+ flags |= Gio.SubprocessFlags.STDERR_SILENCE
+ launcher = Ide.SubprocessLauncher()
+ launcher.set_flags(flags)
+ launcher.set_cwd(GLib.get_home_dir())
+ launcher.set_run_on_host(True)
+ return launcher
+
+ @classmethod
+ def bind_client(klass, provider):
+ context = provider.get_context()
+ self = JavaService.from_context(context)
+ self._ensure_started()
+ self.bind_property('client', provider, 'client', GObject.BindingFlags.SYNC_CREATE)
+
+class JavaDiagnosticProvider(Ide.LspDiagnosticProvider):
+ def do_load(self):
+ JavaService.bind_client(self)
+
+class JavaRenameProvider(Ide.LspRenameProvider):
+ def do_load(self):
+ JavaService.bind_client(self)
+
+class JavaSymbolResolver(Ide.LspSymbolResolver, Ide.SymbolResolver):
+ def do_load(self):
+ JavaService.bind_client(self)
+
+class JavaHighlighter(Ide.LspHighlighter):
+ def do_load(self):
+ JavaService.bind_client(self)
+
+class JavaCompletionProvider(Ide.LspCompletionProvider, Ide.CompletionProvider):
+ def do_load(self, context):
+ JavaService.bind_client(self)
+
+ def do_get_priority(self, context):
+ # This provider only activates when it is very likely that we
+ # want the results. So use high priority (negative is better).
+ return -1000
+
+class JavaFormatter(Ide.LspFormatter, Ide.Formatter):
+ def do_load(self):
+ JavaService.bind_client(self)
+
+class JavaHoverProvider(Ide.LspHoverProvider):
+ def do_prepare(self):
+ self.props.category = 'Java'
+ self.props.priority = 200
+ JavaService.bind_client(self)
+
diff --git a/src/plugins/java-langserv/meson.build b/src/plugins/java-langserv/meson.build
new file mode 100644
index 000000000..00213c6fa
--- /dev/null
+++ b/src/plugins/java-langserv/meson.build
@@ -0,0 +1,13 @@
+if get_option('plugin_java_langserv')
+
+install_data('java_langserver_plugin.py', install_dir: plugindir)
+
+configure_file(
+ input: 'java-langserv.plugin',
+ output: 'java-langserv.plugin',
+ configuration: config_h,
+ install: true,
+ install_dir: plugindir,
+)
+
+endif
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 0c5fd6aa4..1adeae1a9 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -77,6 +77,7 @@ subdir('grep')
subdir('history')
subdir('html-completion')
subdir('html-preview')
+subdir('java-langserv')
subdir('jedi')
subdir('jhbuild')
subdir('line-spacing')
@@ -158,6 +159,7 @@ status += [
'Grep .................. : @0@'.format(get_option('plugin_grep')),
'HTML Completion ....... : @0@'.format(get_option('plugin_html_completion')),
'HTML Preview .......... : @0@'.format(get_option('plugin_html_preview')),
+ 'Java Language Server... : @0@'.format(get_option('plugin_java_langserv')),
'Jedi .................. : @0@'.format(get_option('plugin_jedi')),
'JHBuild ............... : @0@'.format(get_option('plugin_jhbuild')),
'Make .................. : @0@'.format(get_option('plugin_make')),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]