[gnome-builder: 1/5] tsls: add typescript language server




commit 460268aa566ca10d803f9f5171ddccaf16ded6a2
Author: Georg Vienna <georg vienna himbarsoft com>
Date:   Fri Oct 29 18:34:33 2021 +0200

    tsls: add typescript language server

 meson_options.txt                                  |   1 +
 src/libide/lsp/ide-lsp-client.c                    |   1 -
 src/plugins/meson.build                            |   2 +
 src/plugins/ts-language-server/meson.build         |  13 ++
 .../ts-language-server/ts-language-server.plugin   |  16 +++
 .../ts_language_server_plugin.py                   | 145 +++++++++++++++++++++
 6 files changed, 177 insertions(+), 1 deletion(-)
---
diff --git a/meson_options.txt b/meson_options.txt
index 8599060a0..1d29f22ac 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -76,6 +76,7 @@ option('plugin_stylelint', type: 'boolean')
 option('plugin_sysprof', type: 'boolean')
 option('plugin_sysroot', type: 'boolean')
 option('plugin_todo', type: 'boolean')
+option('plugin_ts_language_server', type: 'boolean')
 option('plugin_update_manager', type: 'boolean')
 option('plugin_vala', type: 'boolean')
 option('plugin_vagrant', type: 'boolean', value: false)
diff --git a/src/libide/lsp/ide-lsp-client.c b/src/libide/lsp/ide-lsp-client.c
index 92cc475f1..6995af6c9 100644
--- a/src/libide/lsp/ide-lsp-client.c
+++ b/src/libide/lsp/ide-lsp-client.c
@@ -1524,7 +1524,6 @@ ide_lsp_client_start (IdeLspClient *self)
    */
 
   params = JSONRPC_MESSAGE_NEW (
-    "processId", JSONRPC_MESSAGE_PUT_INT64 (getpid ()),
     "rootUri", JSONRPC_MESSAGE_PUT_STRING (root_uri),
     "rootPath", JSONRPC_MESSAGE_PUT_STRING (root_path),
     "workspaceFolders", "[",
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 582cd1727..b969848bf 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -127,6 +127,7 @@ subdir('sysroot')
 subdir('terminal')
 subdir('testui')
 subdir('todo')
+subdir('ts-language-server')
 subdir('trim-spaces')
 subdir('update-manager')
 subdir('vagrant')
@@ -203,6 +204,7 @@ status += [
   'Sysprof ............... : @0@'.format(get_option('plugin_sysprof')),
   'Sysroot ............... : @0@'.format(get_option('plugin_sysroot')),
   'Todo .................. : @0@'.format(get_option('plugin_todo')),
+  'TS/JS Language Server.. : @0@'.format(get_option('plugin_ts_language_server')),
   'Update Manager ........ : @0@'.format(get_option('plugin_update_manager')),
   'GNOME Vala LS ......... : @0@'.format(get_option('plugin_gvls')),
   'Vala Language Server .. : @0@'.format(get_option('plugin_vls')),
diff --git a/src/plugins/ts-language-server/meson.build b/src/plugins/ts-language-server/meson.build
new file mode 100644
index 000000000..11436b69f
--- /dev/null
+++ b/src/plugins/ts-language-server/meson.build
@@ -0,0 +1,13 @@
+if get_option('plugin_ts_language_server')
+
+install_data('ts_language_server_plugin.py', install_dir: plugindir)
+
+configure_file(
+          input: 'ts-language-server.plugin',
+         output: 'ts-language-server.plugin',
+  configuration: config_h,
+        install: true,
+    install_dir: plugindir,
+)
+
+endif
diff --git a/src/plugins/ts-language-server/ts-language-server.plugin 
b/src/plugins/ts-language-server/ts-language-server.plugin
new file mode 100644
index 000000000..67fd9ec2c
--- /dev/null
+++ b/src/plugins/ts-language-server/ts-language-server.plugin
@@ -0,0 +1,16 @@
+[Plugin]
+Builtin=true
+Copyright=Copyright © 2021 Georg Vienna
+Description=Provides LSP integration for Typescript/Javascript
+Hidden=true
+Loader=python3
+Module=ts_language_server_plugin
+Name=Typescript Language Server Plugin
+X-Builder-ABI=@PACKAGE_ABI@
+X-Completion-Provider-Languages=js,jsx,typescript,typescript-jsx
+X-Symbol-Resolver-Languages=js,jsx,typescript,typescript-jsx
+X-Diagnostic-Provider-Languages=js,jsx,typescript,typescript-jsx
+X-Highlighter-Languages=js,jsx,typescript,typescript-jsx
+X-Hover-Provider-Languages=js,jsx,typescript,typescript-jsx
+X-Rename-Provider-Languages=js,jsx,typescript,typescript-jsx
+X-Formatter-Languages=js,jsx,typescript,typescript-jsx
diff --git a/src/plugins/ts-language-server/ts_language_server_plugin.py 
b/src/plugins/ts-language-server/ts_language_server_plugin.py
new file mode 100644
index 000000000..83b56f344
--- /dev/null
+++ b/src/plugins/ts-language-server/ts_language_server_plugin.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+
+# ts_language_server_plugin.py
+#
+# Copyright 2021 Georg Vienna <georg vienna himbarsoft 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/>.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+import gi
+
+from gi.repository import GLib
+from gi.repository import Gio
+from gi.repository import GObject
+from gi.repository import Ide
+
+DEV_MODE = True
+
+class TypescriptService(Ide.Object):
+    _client = None
+    _has_started = False
+    _supervisor = None
+
+    @classmethod
+    def from_context(klass, context):
+        return context.ensure_child_typed(TypescriptService)
+
+    @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 _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 typescript-language-server from there
+            workdir = self.get_context().ref_workdir()
+            launcher.set_cwd(workdir.get_path())
+
+            # this needs https://github.com/typescript-language-server/typescript-language-server installed 
on the host
+            launcher.push_argv("typescript-language-server")
+            launcher.push_argv("--stdio")
+
+            # 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('javascript')
+        self._client.add_language('typescript')
+        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_run_on_host(True)
+        return launcher
+
+    @classmethod
+    def bind_client(klass, provider):
+        context = provider.get_context()
+        self = TypescriptService.from_context(context)
+        self._ensure_started()
+        self.bind_property('client', provider, 'client', GObject.BindingFlags.SYNC_CREATE)
+
+class TypescriptDiagnosticProvider(Ide.LspDiagnosticProvider, Ide.DiagnosticProvider):
+    def do_load(self):
+        TypescriptService.bind_client(self)
+
+class TypescriptCompletionProvider(Ide.LspCompletionProvider, Ide.CompletionProvider):
+    def do_load(self, context):
+        TypescriptService.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 TypescriptSymbolResolver(Ide.LspSymbolResolver, Ide.SymbolResolver):
+    def do_load(self):
+        TypescriptService.bind_client(self)
+
+class TypescriptHighlighter(Ide.LspHighlighter, Ide.Highlighter):
+    def do_load(self):
+        TypescriptService.bind_client(self)
+
+class TypescriptFormatter(Ide.LspFormatter, Ide.Formatter):
+    def do_load(self):
+        TypescriptService.bind_client(self)
+
+class TypescriptHoverProvider(Ide.LspHoverProvider, Ide.HoverProvider):
+    def do_prepare(self):
+        self.props.category = 'Typescript'
+        self.props.priority = 200
+        TypescriptService.bind_client(self)
+
+class TypescriptRenameProvider(Ide.LspRenameProvider, Ide.RenameProvider):
+    def do_load(self):
+        TypescriptService.bind_client(self)
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]