[gnome-builder/wip/beniofel/vala-langserv] Add vala language server (wip)
- From: Ben Iofel <beniofel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/beniofel/vala-langserv] Add vala language server (wip)
- Date: Wed, 2 Aug 2017 14:44:08 +0000 (UTC)
commit 0e1e54bddb0f806d890311555602ff6d771641f4
Author: Ben Iofel <iofelben gmail com>
Date: Wed Aug 2 15:43:41 2017 +0100
Add vala language server (wip)
meson_options.txt | 1 +
plugins/meson.build | 2 +
plugins/vala-langserv/meson.build | 13 ++
plugins/vala-langserv/vala-langserv.plugin | 14 ++
plugins/vala-langserv/vala_langserv_plugin.py | 172 +++++++++++++++++++++++++
5 files changed, 202 insertions(+), 0 deletions(-)
---
diff --git a/meson_options.txt b/meson_options.txt
index b3ca444..f8638aa 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -70,5 +70,6 @@ option('with_sysprof', type: 'boolean')
option('with_terminal', type: 'boolean')
option('with_todo', type: 'boolean')
option('with_vala_pack', type: 'boolean')
+option('with_vala_langserv', type: 'boolean')
option('with_valgrind', type: 'boolean')
option('with_xml_pack', type: 'boolean')
diff --git a/plugins/meson.build b/plugins/meson.build
index dbfcd84..18b1a34 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -59,6 +59,7 @@ subdir('sysprof')
subdir('terminal')
subdir('todo')
subdir('vala-pack')
+subdir('vala-langserv')
subdir('valgrind')
subdir('xml-pack')
@@ -112,6 +113,7 @@ status += [
'Terminal .............. : @0@'.format(get_option('with_terminal')),
'Todo .................. : @0@'.format(get_option('with_todo')),
'Vala Language Pack .... : @0@'.format(get_option('with_vala_pack')),
+ 'Vala Language Sever ... : @0@'.format(get_option('with_vala_langserv')),
'Valgrind .............. : @0@'.format(get_option('with_valgrind')),
'XML Language Pack ..... : @0@'.format(get_option('with_xml_pack')),
'', '',
diff --git a/plugins/vala-langserv/meson.build b/plugins/vala-langserv/meson.build
new file mode 100644
index 0000000..6002d6d
--- /dev/null
+++ b/plugins/vala-langserv/meson.build
@@ -0,0 +1,13 @@
+if get_option('with_vala_langserv')
+
+install_data('vala_langserv_plugin.py', install_dir: plugindir)
+
+configure_file(
+ input: 'vala-langserv.plugin',
+ output: 'vala-langserv.plugin',
+ configuration: configuration_data(),
+ install: true,
+ install_dir: plugindir,
+)
+
+endif
diff --git a/plugins/vala-langserv/vala-langserv.plugin b/plugins/vala-langserv/vala-langserv.plugin
new file mode 100644
index 0000000..a0e3152
--- /dev/null
+++ b/plugins/vala-langserv/vala-langserv.plugin
@@ -0,0 +1,14 @@
+[Plugin]
+Module=vala_langserv_plugin
+Loader=python3
+Name=Vala Language Server Integration
+Description=Provides auto-completion, diagnostics, and other IDE features
+Authors=Ben Iofel <iofelben gmail com>
+Copyright=Copyright © 2017 Ben Iofel
+Builtin=true
+X-Completion-Provider-Languages=vala
+X-Diagnostic-Provider-Languages=vala
+X-Formatter-Languages=vala
+X-Highlighter-Languages=vala
+X-Rename-Provider-Languages=vala
+X-Symbol-Resolver-Languages=vala
diff --git a/plugins/vala-langserv/vala_langserv_plugin.py b/plugins/vala-langserv/vala_langserv_plugin.py
new file mode 100644
index 0000000..18912a4
--- /dev/null
+++ b/plugins/vala-langserv/vala_langserv_plugin.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+
+# vala_langserv_plugin.py
+#
+# Copyright (C) 2016 Christian Hergert <chergert redhat 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 Vala Language Server.
+It builds off the generic language service components in libide
+by bridging them to our supervised Vala Language Server.
+"""
+
+import gi
+import os
+
+gi.require_version('Ide', '1.0')
+gi.require_version('GtkSource', '3.0')
+
+from gi.repository import GLib
+from gi.repository import Gio
+from gi.repository import GObject
+from gi.repository import GtkSource
+from gi.repository import Ide
+
+DEV_MODE = True
+
+class ValaService(Ide.Object, Ide.Service):
+ _client = None
+ _has_started = False
+ _supervisor = None
+
+ @GObject.Property(type=Ide.LangservClient)
+ def client(self):
+ return self._client
+
+ @client.setter
+ def client(self, value):
+ self._client = value
+ self.notify('client')
+
+ def do_stop(self):
+ """
+ Stops the Vala Language Server upon request to shutdown the
+ ValaService.
+ """
+ if self._supervisor:
+ supervisor, self._supervisor = self._supervisor, None
+ supervisor.stop()
+
+ def _ensure_started(self):
+ """
+ Start the vala service which provides communication with the
+ Vala Language Server. We supervise our own instance of the
+ language server and restart it as necessary using the
+ Ide.SubprocessSupervisor.
+
+ Various extension points (diagnostics, symbol providers, etc) use
+ the ValaService to access the vala components they need.
+ """
+ # To avoid starting the `rls` process unconditionally at startup,
+ # we 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
+
+ # Setup a launcher to spawn the vala language server
+ launcher = self._create_launcher()
+ launcher.set_clear_env(False)
+ if DEV_MODE:
+ launcher.setenv('JSONRPC_DEBUG', '1', True)
+
+ # Locate the directory of the project and run rls from there.
+ workdir = self.get_context().get_vcs().get_working_directory()
+ launcher.set_cwd(workdir.get_path())
+
+ path_to_vls = "/home/ben/dev/vala-language-server/build/vala-language-server"
+
+ # Setup our Argv. We want to communicate over STDIN/STDOUT,
+ # so it does not require any command line options.
+ launcher.push_argv(path_to_vls)
+
+ # 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._vls_spawned)
+ self._supervisor.set_launcher(launcher)
+ self._supervisor.start()
+
+ def _vls_spawned(self, supervisor, subprocess):
+ """
+ This callback is executed when the `vls` process is spawned.
+ We can use the stdin/stdout to create a channel for our
+ LangservClient.
+ """
+ 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 = Ide.LangservClient.new(self.get_context(), io_stream)
+ self._client.add_language('vala')
+ self._client.start()
+ self.notify('client')
+
+ def _create_launcher(self):
+ """
+ Creates a launcher to be used by the vala service. This needs
+ to be run on the host because we do not currently bundle vala
+ inside our flatpak.
+
+ In the future, we might be able to rely on the runtime for
+ the tooling. Maybe even the program if flatpak-builder has
+ prebuilt our dependencies.
+ """
+ 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):
+ """
+ This helper tracks changes to our client as it might happen when
+ our `rls` process has crashed.
+ """
+ context = provider.get_context()
+ self = context.get_service_typed(ValaService)
+ self._ensure_started()
+ self.bind_property('client', provider, 'client', GObject.BindingFlags.SYNC_CREATE)
+
+class ValaDiagnosticProvider(Ide.LangservDiagnosticProvider):
+ def do_load(self):
+ ValaService.bind_client(self)
+
+class ValaCompletionProvider(Ide.LangservCompletionProvider):
+ def do_load(self, context):
+ ValaService.bind_client(self)
+
+class ValaRenameProvider(Ide.LangservRenameProvider):
+ def do_load(self):
+ ValaService.bind_client(self)
+
+class ValaSymbolResolver(Ide.LangservSymbolResolver):
+ def do_load(self):
+ ValaService.bind_client(self)
+
+class ValaHighlighter(Ide.LangservHighlighter):
+ def do_load(self):
+ ValaService.bind_client(self)
+
+class ValaFormatter(Ide.LangservFormatter):
+ def do_load(self):
+ ValaService.bind_client(self)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]