[gnome-builder/wip/chergert/lsp-plugin-loader: 6/24] libide/lsp: implement generic LSP server support
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/lsp-plugin-loader: 6/24] libide/lsp: implement generic LSP server support
- Date: Fri, 14 Oct 2022 17:13:04 +0000 (UTC)
commit e5ba93c9b1fd42d85cbc22c3aaf2d31ffeebb478
Author: Christian Hergert <chergert redhat com>
Date: Tue Oct 11 10:34:21 2022 -0500
libide/lsp: implement generic LSP server support
This provides dynamic type registration for language server plugins so
that it does not require writing code in the plugin (unless we end up
supporting a very odd Language Server).
This will very likely expose some issues in our IdeLspClient that we
need to figure out, so I expect a bit of fallout as a side-effect.
Additionally, this is going to require that we abstract LSP settings
using something like `.vscode/settings.json`. Currently, our format
differs a bit from that (and still needs some implementation) but this
moves us in the right direction.
The next steps are going to be making that format more familiar, along
with making it loaded as part of LSP configuration. Beyond that, we need
to make more generic plumbing work as expected by the LSP peers;
especially when dealing with capabilities.
Additional fallout from this will be the temporary loss of some
configuration of LSPs like rust-analyzer which we had tweais.ui for. We
can probably introduce something like that using tweaks.ui and
auto-load/bind those to known settings options in settings.json.
Bundled language servers will also be deleted with this patch series as
we don't want to be doing that anymore anyway. We expect that build
containers contain the SDK tooling.
.../lsp/ide-lsp-plugin-code-action-provider.c | 100 ++++++
.../lsp/ide-lsp-plugin-completion-provider.c | 89 ++++++
.../lsp/ide-lsp-plugin-diagnostic-provider.c | 100 ++++++
src/libide/lsp/ide-lsp-plugin-formatter.c | 100 ++++++
src/libide/lsp/ide-lsp-plugin-highlighter.c | 100 ++++++
src/libide/lsp/ide-lsp-plugin-hover-provider.c | 88 +++++
src/libide/lsp/ide-lsp-plugin-private.h | 78 +++++
src/libide/lsp/ide-lsp-plugin-rename-provider.c | 100 ++++++
src/libide/lsp/ide-lsp-plugin-symbol-resolver.c | 100 ++++++
src/libide/lsp/ide-lsp-plugin.c | 354 +++++++++++++++++++++
src/libide/lsp/ide-lsp-plugin.h | 32 ++
src/libide/lsp/libide-lsp.h | 1 +
src/libide/lsp/meson.build | 11 +
13 files changed, 1253 insertions(+)
---
diff --git a/src/libide/lsp/ide-lsp-plugin-code-action-provider.c
b/src/libide/lsp/ide-lsp-plugin-code-action-provider.c
new file mode 100644
index 000000000..672955cd6
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-code-action-provider.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-code-action-provider.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-code-action-provider"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-code-action-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginCodeActionProviderClass
+{
+ IdeLspCodeActionProviderClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginCodeActionProviderClass;
+
+static void
+ide_lsp_plugin_code_action_provider_load (IdeCodeActionProvider *provider)
+{
+ IdeLspPluginCodeActionProviderClass *klass = (IdeLspPluginCodeActionProviderClass *)(((GTypeInstance
*)provider)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (provider));
+}
+
+static void
+ide_lsp_plugin_code_action_provider_class_init (IdeLspPluginCodeActionProviderClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_code_action_provider_iface_init (IdeCodeActionProviderInterface *iface)
+{
+ iface->load = ide_lsp_plugin_code_action_provider_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_code_action_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->code_action_provider_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+CodeActionProvider", NULL);
+
+ info->code_action_provider_type =
+ g_type_register_static (IDE_TYPE_LSP_CODE_ACTION_PROVIDER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginCodeActionProviderClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_code_action_provider_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspCodeActionProvider),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->code_action_provider_type,
+ IDE_TYPE_CODE_ACTION_PROVIDER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_code_action_provider_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->code_action_provider_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-completion-provider.c
b/src/libide/lsp/ide-lsp-plugin-completion-provider.c
new file mode 100644
index 000000000..2db770fcc
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-completion-provider.c
@@ -0,0 +1,89 @@
+/* ide-lsp-plugin-completion-provider.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-completion-provider"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include "ide-lsp-completion-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginCompletionProviderClass
+{
+ IdeLspCompletionProviderClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginCompletionProviderClass;
+
+static void
+ide_lsp_plugin_completion_provider_load (IdeLspCompletionProvider *provider)
+{
+ IdeLspPluginCompletionProviderClass *klass = (IdeLspPluginCompletionProviderClass *)(((GTypeInstance
*)provider)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (provider));
+}
+
+static void
+ide_lsp_plugin_completion_provider_class_init (IdeLspPluginCompletionProviderClass *klass,
+ IdeLspPluginInfo *info)
+{
+ IdeLspCompletionProviderClass *completion_class = IDE_LSP_COMPLETION_PROVIDER_CLASS (klass);
+
+ completion_class->load = ide_lsp_plugin_completion_provider_load;
+
+ klass->info = info;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_completion_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->completion_provider_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+CompletionProvider", NULL);
+
+ info->completion_provider_type =
+ g_type_register_static (IDE_TYPE_LSP_COMPLETION_PROVIDER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginCompletionProviderClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_completion_provider_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspCompletionProvider),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ }
+
+ return g_object_newv (info->completion_provider_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-diagnostic-provider.c
b/src/libide/lsp/ide-lsp-plugin-diagnostic-provider.c
new file mode 100644
index 000000000..3eade89ad
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-diagnostic-provider.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-diagnostic-provider.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-diagnostic-provider"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-diagnostic-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginDiagnosticProviderClass
+{
+ IdeLspDiagnosticProviderClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginDiagnosticProviderClass;
+
+static void
+ide_lsp_plugin_diagnostic_provider_load (IdeDiagnosticProvider *provider)
+{
+ IdeLspPluginDiagnosticProviderClass *klass = (IdeLspPluginDiagnosticProviderClass *)(((GTypeInstance
*)provider)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (provider));
+}
+
+static void
+ide_lsp_plugin_diagnostic_provider_class_init (IdeLspPluginDiagnosticProviderClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_diagnostic_provider_iface_init (IdeDiagnosticProviderInterface *iface)
+{
+ iface->load = ide_lsp_plugin_diagnostic_provider_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_diagnostic_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->diagnostic_provider_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+DiagnosticProvider", NULL);
+
+ info->diagnostic_provider_type =
+ g_type_register_static (IDE_TYPE_LSP_DIAGNOSTIC_PROVIDER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginDiagnosticProviderClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_diagnostic_provider_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspDiagnosticProvider),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->diagnostic_provider_type,
+ IDE_TYPE_DIAGNOSTIC_PROVIDER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_diagnostic_provider_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->diagnostic_provider_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-formatter.c b/src/libide/lsp/ide-lsp-plugin-formatter.c
new file mode 100644
index 000000000..5ec5d990b
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-formatter.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-formatter.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-formatter"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-formatter.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginFormatterClass
+{
+ IdeLspFormatterClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginFormatterClass;
+
+static void
+ide_lsp_plugin_formatter_load (IdeFormatter *resolver)
+{
+ IdeLspPluginFormatterClass *klass = (IdeLspPluginFormatterClass *)(((GTypeInstance *)resolver)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (resolver));
+}
+
+static void
+ide_lsp_plugin_formatter_class_init (IdeLspPluginFormatterClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_formatter_iface_init (IdeFormatterInterface *iface)
+{
+ iface->load = ide_lsp_plugin_formatter_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_formatter (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->formatter_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+Formatter", NULL);
+
+ info->formatter_type =
+ g_type_register_static (IDE_TYPE_LSP_FORMATTER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginFormatterClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_formatter_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspFormatter),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->formatter_type,
+ IDE_TYPE_FORMATTER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_formatter_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->formatter_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-highlighter.c b/src/libide/lsp/ide-lsp-plugin-highlighter.c
new file mode 100644
index 000000000..bb1d577db
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-highlighter.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-highlighter.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-highlighter"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-highlighter.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginHighlighterClass
+{
+ IdeLspHighlighterClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginHighlighterClass;
+
+static void
+ide_lsp_plugin_highlighter_load (IdeHighlighter *resolver)
+{
+ IdeLspPluginHighlighterClass *klass = (IdeLspPluginHighlighterClass *)(((GTypeInstance
*)resolver)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (resolver));
+}
+
+static void
+ide_lsp_plugin_highlighter_class_init (IdeLspPluginHighlighterClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_highlighter_iface_init (IdeHighlighterInterface *iface)
+{
+ iface->load = ide_lsp_plugin_highlighter_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_highlighter (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->highlighter_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+Highlighter", NULL);
+
+ info->highlighter_type =
+ g_type_register_static (IDE_TYPE_LSP_HIGHLIGHTER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginHighlighterClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_highlighter_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspHighlighter),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->highlighter_type,
+ IDE_TYPE_HIGHLIGHTER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_highlighter_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->highlighter_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-hover-provider.c b/src/libide/lsp/ide-lsp-plugin-hover-provider.c
new file mode 100644
index 000000000..ba0fec227
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-hover-provider.c
@@ -0,0 +1,88 @@
+/* ide-lsp-plugin-hover-provider.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-hover-provider"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-hover-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginHoverProviderClass
+{
+ IdeLspHoverProviderClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginHoverProviderClass;
+
+static void
+ide_lsp_plugin_hover_provider_prepare (IdeLspHoverProvider *provider)
+{
+ IdeLspPluginHoverProviderClass *klass = (IdeLspPluginHoverProviderClass *)(((GTypeInstance
*)provider)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (provider));
+}
+
+static void
+ide_lsp_plugin_hover_provider_class_init (IdeLspPluginHoverProviderClass *klass,
+ IdeLspPluginInfo *info)
+{
+ IDE_LSP_HOVER_PROVIDER_CLASS (klass)->prepare = ide_lsp_plugin_hover_provider_prepare;
+ klass->info = info;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_hover_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->hover_provider_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+HoverProvider", NULL);
+
+ info->hover_provider_type =
+ g_type_register_static (IDE_TYPE_LSP_HOVER_PROVIDER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginHoverProviderClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_hover_provider_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspHoverProvider),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ }
+
+ return g_object_newv (info->hover_provider_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-private.h b/src/libide/lsp/ide-lsp-plugin-private.h
new file mode 100644
index 000000000..a25ee4522
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-private.h
@@ -0,0 +1,78 @@
+/* ide-lsp-plugin-private.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ide-lsp-plugin.h"
+
+G_BEGIN_DECLS
+
+typedef struct _IdeLspPluginInfo
+{
+ char *module_name;
+ char **command;
+ char **languages;
+ GBytes *default_settings;
+ GType service_type;
+ GType completion_provider_type;
+ GType code_action_provider_type;
+ GType diagnostic_provider_type;
+ GType formatter_type;
+ GType highlighter_type;
+ GType hover_provider_type;
+ GType rename_provider_type;
+ GType symbol_resolver_type;
+} IdeLspPluginInfo;
+
+IdeLspPluginInfo *ide_lsp_plugin_info_ref (IdeLspPluginInfo *info);
+void ide_lsp_plugin_info_unref (IdeLspPluginInfo *info);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+void ide_lsp_plugin_remove_plugin_info_param (guint *n_parameters,
+ GParameter *parameters);
+GObject *ide_lsp_plugin_create_code_action_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_completion_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_diagnostic_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_formatter (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_highlighter (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_hover_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_rename_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+GObject *ide_lsp_plugin_create_symbol_resolver (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+G_END_DECLS
diff --git a/src/libide/lsp/ide-lsp-plugin-rename-provider.c b/src/libide/lsp/ide-lsp-plugin-rename-provider.c
new file mode 100644
index 000000000..c436db506
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-rename-provider.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-rename-provider.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-rename-provider"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-rename-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginRenameProviderClass
+{
+ IdeLspRenameProviderClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginRenameProviderClass;
+
+static void
+ide_lsp_plugin_rename_provider_load (IdeRenameProvider *provider)
+{
+ IdeLspPluginRenameProviderClass *klass = (IdeLspPluginRenameProviderClass *)(((GTypeInstance
*)provider)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (provider));
+}
+
+static void
+ide_lsp_plugin_rename_provider_class_init (IdeLspPluginRenameProviderClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_rename_provider_iface_init (IdeRenameProviderInterface *iface)
+{
+ iface->load = ide_lsp_plugin_rename_provider_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_rename_provider (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->rename_provider_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+RenameProvider", NULL);
+
+ info->rename_provider_type =
+ g_type_register_static (IDE_TYPE_LSP_RENAME_PROVIDER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginRenameProviderClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_rename_provider_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspRenameProvider),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->rename_provider_type,
+ IDE_TYPE_RENAME_PROVIDER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_rename_provider_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->rename_provider_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin-symbol-resolver.c b/src/libide/lsp/ide-lsp-plugin-symbol-resolver.c
new file mode 100644
index 000000000..34fa42747
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin-symbol-resolver.c
@@ -0,0 +1,100 @@
+/* ide-lsp-plugin-symbol-resolver.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin-symbol-resolver"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "ide-lsp-symbol-resolver.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef struct _IdeLspPluginSymbolResolverClass
+{
+ IdeLspSymbolResolverClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginSymbolResolverClass;
+
+static void
+ide_lsp_plugin_symbol_resolver_load (IdeSymbolResolver *resolver)
+{
+ IdeLspPluginSymbolResolverClass *klass = (IdeLspPluginSymbolResolverClass *)(((GTypeInstance
*)resolver)->g_class);
+ g_autoptr(IdeLspServiceClass) service_class = g_type_class_ref (klass->info->service_type);
+
+ ide_lsp_service_class_bind_client (service_class, IDE_OBJECT (resolver));
+}
+
+static void
+ide_lsp_plugin_symbol_resolver_class_init (IdeLspPluginSymbolResolverClass *klass,
+ IdeLspPluginInfo *info)
+{
+ klass->info = info;
+}
+
+static void
+ide_lsp_plugin_symbol_resolver_iface_init (IdeSymbolResolverInterface *iface)
+{
+ iface->load = ide_lsp_plugin_symbol_resolver_load;
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+GObject *
+ide_lsp_plugin_create_symbol_resolver (guint n_parameters,
+ GParameter *parameters,
+ IdeLspPluginInfo *info)
+{
+ ide_lsp_plugin_remove_plugin_info_param (&n_parameters, parameters);
+
+ if G_UNLIKELY (info->symbol_resolver_type == G_TYPE_INVALID)
+ {
+ g_autofree char *name = g_strconcat (info->module_name, "+SymbolResolver", NULL);
+
+ info->symbol_resolver_type =
+ g_type_register_static (IDE_TYPE_LSP_SYMBOL_RESOLVER,
+ name,
+ &(GTypeInfo) {
+ sizeof (IdeLspPluginSymbolResolverClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_symbol_resolver_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspSymbolResolver),
+ 0,
+ NULL,
+ NULL,
+ },
+ G_TYPE_FLAG_FINAL);
+ g_type_add_interface_static (info->symbol_resolver_type,
+ IDE_TYPE_SYMBOL_RESOLVER,
+ &(GInterfaceInfo) {
+ (GInterfaceInitFunc)(void (*)
(void))ide_lsp_plugin_symbol_resolver_iface_init,
+ NULL,
+ NULL,
+ });
+ }
+
+ return g_object_newv (info->symbol_resolver_type, n_parameters, parameters);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin.c b/src/libide/lsp/ide-lsp-plugin.c
new file mode 100644
index 000000000..1d6bedc40
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin.c
@@ -0,0 +1,354 @@
+/* ide-lsp-plugin.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-lsp-plugin"
+
+#include "config.h"
+
+#include "ide-lsp-diagnostic-provider.h"
+#include "ide-lsp-symbol-resolver.h"
+#include "ide-lsp-highlighter.h"
+#include "ide-lsp-formatter.h"
+#include "ide-lsp-hover-provider.h"
+#include "ide-lsp-rename-provider.h"
+#include "ide-lsp-code-action-provider.h"
+#include "ide-lsp-plugin-private.h"
+#include "ide-lsp-service.h"
+
+typedef enum _IdeLspPluginFeatures
+{
+ IDE_LSP_PLUGIN_FEATURES_DIAGNOSTICS = 1 << 0,
+ IDE_LSP_PLUGIN_FEATURES_COMPLETION = 1 << 1,
+ IDE_LSP_PLUGIN_FEATURES_SYMBOL_RESOLVER = 1 << 2,
+ IDE_LSP_PLUGIN_FEATURES_HIGHLIGHTER = 1 << 3,
+ IDE_LSP_PLUGIN_FEATURES_FORMATTER = 1 << 4,
+ IDE_LSP_PLUGIN_FEATURES_HOVER = 1 << 5,
+ IDE_LSP_PLUGIN_FEATURES_RENAME = 1 << 6,
+ IDE_LSP_PLUGIN_FEATURES_CODE_ACTION = 1 << 7,
+ IDE_LSP_PLUGIN_FEATURES_ALL = ~0,
+} IdeLspPluginFeatures;
+
+IdeLspPluginInfo *
+ide_lsp_plugin_info_ref (IdeLspPluginInfo *self)
+{
+ return g_atomic_rc_box_acquire (self);
+}
+
+static void
+ide_lsp_plugin_info_finalize (gpointer data)
+{
+ IdeLspPluginInfo *self = data;
+
+ g_clear_pointer (&self->command, g_strfreev);
+ g_clear_pointer (&self->languages, g_strfreev);
+ g_clear_pointer (&self->default_settings, g_bytes_unref);
+ g_clear_pointer (&self->module_name, g_free);
+}
+
+void
+ide_lsp_plugin_info_unref (IdeLspPluginInfo *info)
+{
+ g_atomic_rc_box_release_full (info, ide_lsp_plugin_info_finalize);
+}
+
+static IdeLspPluginInfo *
+ide_lsp_plugin_info_new (void)
+{
+ return g_atomic_rc_box_new0 (IdeLspPluginInfo);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeLspPluginInfo, ide_lsp_plugin_info_unref)
+
+static GBytes *
+load_bytes (const char *path)
+{
+ if (path == NULL)
+ {
+ return NULL;
+ }
+ else if (g_str_has_prefix (path, "resource://"))
+ {
+ return g_resources_lookup_data (path, 0, NULL);
+ }
+ else
+ {
+ g_autoptr(GFile) file = g_file_new_for_path (path);
+ return g_file_load_bytes (file, NULL, NULL, NULL);
+ }
+}
+
+typedef struct _IdeLspPluginService
+{
+ IdeLspService parent_instance;
+} IdeLspPluginService;
+
+typedef struct _IdeLspPluginServiceClass
+{
+ IdeLspServiceClass parent_class;
+ IdeLspPluginInfo *info;
+} IdeLspPluginServiceClass;
+
+static void
+ide_lsp_plugin_service_configure_client (IdeLspService *service,
+ IdeLspClient *client)
+{
+ IdeLspPluginService *self = (IdeLspPluginService *)service;
+ IdeLspPluginServiceClass *klass = (IdeLspPluginServiceClass *)((GTypeInstance *)service)->g_class;
+ g_autoptr(GVariant) options = NULL;
+ IdeContext *context;
+
+ g_assert (IDE_IS_LSP_SERVICE (self));
+ g_assert (IDE_IS_LSP_CLIENT (client));
+
+ if (klass->info->languages != NULL)
+ {
+ for (guint i = 0; klass->info->languages[i]; i++)
+ ide_lsp_client_add_language (client, klass->info->languages[i]);
+ }
+
+ if (!(context = ide_object_get_context (IDE_OBJECT (service))))
+ return;
+
+ /* TODO: User configurable settings */
+
+#if 0
+ if (klass->info->default_settings)
+ ide_lsp_client_set_initialization_options (client, klass->data->default_settings);
+#endif
+}
+
+static void
+ide_lsp_plugin_service_prepare_run_context (IdeLspService *service,
+ IdePipeline *pipeline,
+ IdeRunContext *run_context)
+{
+ IdeLspPluginServiceClass *klass;
+
+ g_assert (IDE_IS_LSP_SERVICE (service));
+ g_assert (!pipeline || IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+
+ klass = (IdeLspPluginServiceClass *)G_OBJECT_GET_CLASS (service);
+
+ if (klass->info->command[0] && klass->info->command[1])
+ ide_run_context_append_args (run_context, (const char * const *)&klass->info->command[1]);
+}
+
+static void
+ide_lsp_plugin_service_class_init (IdeLspPluginServiceClass *klass,
+ IdeLspPluginInfo *info)
+{
+ IdeLspServiceClass *service_class = IDE_LSP_SERVICE_CLASS (klass);
+
+ klass->info = info;
+
+ service_class->configure_client = ide_lsp_plugin_service_configure_client;
+ service_class->prepare_run_context = ide_lsp_plugin_service_prepare_run_context;
+}
+
+static void
+ide_lsp_plugin_service_init (IdeLspPluginService *self,
+ IdeLspPluginServiceClass *klass)
+{
+ ide_lsp_service_set_program (IDE_LSP_SERVICE (self), klass->info->command[0]);
+}
+
+static GType
+ide_lsp_plugin_register_service_gtype (IdeLspPluginInfo *info)
+{
+ g_autofree char *type_name = g_strconcat (info->module_name, "+IdeLspPluginService", NULL);
+ GTypeInfo type_info =
+ {
+ sizeof (IdeLspPluginServiceClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)ide_lsp_plugin_service_class_init,
+ NULL,
+ ide_lsp_plugin_info_ref (info),
+ sizeof (IdeLspPluginService),
+ 0,
+ (GInstanceInitFunc)ide_lsp_plugin_service_init,
+ NULL,
+ };
+ return g_type_register_static (IDE_TYPE_LSP_SERVICE, type_name, &type_info, G_TYPE_FLAG_FINAL);
+}
+
+static void
+ide_lsp_plugin_register (PeasObjectModule *object_module,
+ IdeLspPluginFeatures features,
+ const char * const *command,
+ const char * const *languages,
+ GBytes *default_settings)
+{
+ g_autoptr(IdeLspPluginInfo) info = NULL;
+
+ g_return_if_fail (PEAS_IS_OBJECT_MODULE (object_module));
+
+ info = ide_lsp_plugin_info_new ();
+ info->module_name = g_strdup (peas_object_module_get_module_name (object_module));
+ info->command = g_strdupv ((char **)command);
+ info->languages = g_strdupv ((char **)languages);
+ info->default_settings = default_settings ? g_bytes_ref (default_settings) : NULL;
+ info->service_type = ide_lsp_plugin_register_service_gtype (info);
+
+ g_log (info->module_name,
+ G_LOG_LEVEL_DEBUG,
+ "Registered type %s",
+ g_type_name (info->service_type));
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_DIAGNOSTICS) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_DIAGNOSTIC_PROVIDER,
+
(PeasFactoryFunc)ide_lsp_plugin_create_diagnostic_provider,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_COMPLETION) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ GTK_SOURCE_TYPE_COMPLETION_PROVIDER,
+
(PeasFactoryFunc)ide_lsp_plugin_create_completion_provider,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_SYMBOL_RESOLVER) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_SYMBOL_RESOLVER,
+ (PeasFactoryFunc)ide_lsp_plugin_create_symbol_resolver,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_HIGHLIGHTER) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_HIGHLIGHTER,
+ (PeasFactoryFunc)ide_lsp_plugin_create_highlighter,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_FORMATTER) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_FORMATTER,
+ (PeasFactoryFunc)ide_lsp_plugin_create_formatter,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_HOVER) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ GTK_SOURCE_TYPE_HOVER_PROVIDER,
+ (PeasFactoryFunc)ide_lsp_plugin_create_hover_provider,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_RENAME) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_RENAME_PROVIDER,
+ (PeasFactoryFunc)ide_lsp_plugin_create_rename_provider,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+
+ if ((features & IDE_LSP_PLUGIN_FEATURES_CODE_ACTION) != 0)
+ peas_object_module_register_extension_factory (object_module,
+ IDE_TYPE_CODE_ACTION_PROVIDER,
+
(PeasFactoryFunc)ide_lsp_plugin_create_code_action_provider,
+ ide_lsp_plugin_info_ref (info),
+ (GDestroyNotify)ide_lsp_plugin_info_unref);
+}
+
+void
+ide_lsp_plugin_register_types (PeasObjectModule *object_module)
+{
+ g_autofree char *x_lsp_languages = NULL;
+ g_autofree char *settings_path = NULL;
+ g_autoptr(GBytes) default_settings = NULL;
+ g_autoptr(GError) error = NULL;
+ g_auto(GStrv) argv = NULL;
+ g_auto(GStrv) languages = NULL;
+ PeasPluginInfo *plugin_info;
+ PeasEngine *engine;
+ const char *data_dir;
+ const char *module_name;
+ const char *x_lsp_command;
+ const char *x_lsp_settings;
+ int argc;
+
+ g_return_if_fail (PEAS_IS_OBJECT_MODULE (object_module));
+
+ engine = peas_engine_get_default ();
+ module_name = peas_object_module_get_module_name (object_module);
+ plugin_info = peas_engine_get_plugin_info (engine, module_name);
+ x_lsp_command = peas_plugin_info_get_external_data (plugin_info, "LSP-Command");
+ x_lsp_languages = g_strdup (peas_plugin_info_get_external_data (plugin_info, "LSP-Languages"));
+ x_lsp_settings = peas_plugin_info_get_external_data (plugin_info, "LSP-Settings");
+ data_dir = peas_plugin_info_get_data_dir (plugin_info);
+
+ if (x_lsp_command == NULL)
+ {
+ g_critical ("Plugin %s missing X-LSP-Command=", module_name);
+ return;
+ }
+
+ if (x_lsp_languages == NULL)
+ {
+ g_critical ("Plugin %s missing X-LSP-Languages=", module_name);
+ return;
+ }
+
+ languages = g_strsplit (g_strdelimit (x_lsp_languages, ",", ';'), ";", 0);
+
+ if (!g_shell_parse_argv (x_lsp_command, &argc, &argv, &error))
+ {
+ g_critical ("Plugin %s provides invalid X-LSP-Command=%s: %s",
+ module_name, x_lsp_command, error->message);
+ return;
+ }
+
+ if (x_lsp_settings == NULL)
+ x_lsp_settings = "settings.json";
+
+ settings_path = g_build_filename (data_dir, x_lsp_settings, NULL);
+ default_settings = load_bytes (settings_path);
+
+ ide_lsp_plugin_register (object_module,
+ IDE_LSP_PLUGIN_FEATURES_ALL,
+ (const char * const *)argv,
+ (const char * const *)languages,
+ default_settings);
+}
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+void
+ide_lsp_plugin_remove_plugin_info_param (guint *n_parameters,
+ GParameter *parameters)
+{
+ static GType plugin_info_type;
+ const GParameter *param;
+
+ if (*n_parameters == 0)
+ return;
+
+ if G_UNLIKELY (plugin_info_type == G_TYPE_INVALID)
+ plugin_info_type = PEAS_TYPE_PLUGIN_INFO;
+
+ param = ¶meters[(*n_parameters) - 1];
+
+ if (G_VALUE_TYPE (¶m->value) == plugin_info_type &&
+ strcmp (param->name, "plugin-info") == 0)
+ (*n_parameters)--;
+}
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
diff --git a/src/libide/lsp/ide-lsp-plugin.h b/src/libide/lsp/ide-lsp-plugin.h
new file mode 100644
index 000000000..6c2284632
--- /dev/null
+++ b/src/libide/lsp/ide-lsp-plugin.h
@@ -0,0 +1,32 @@
+/* ide-lsp-plugin.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libpeas/peas.h>
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+IDE_AVAILABLE_IN_44
+void ide_lsp_plugin_register_types (PeasObjectModule *object_module);
+
+G_END_DECLS
diff --git a/src/libide/lsp/libide-lsp.h b/src/libide/lsp/libide-lsp.h
index 765bd7176..362fad933 100644
--- a/src/libide/lsp/libide-lsp.h
+++ b/src/libide/lsp/libide-lsp.h
@@ -38,6 +38,7 @@
#include "ide-lsp-formatter.h"
#include "ide-lsp-highlighter.h"
#include "ide-lsp-hover-provider.h"
+#include "ide-lsp-plugin.h"
#include "ide-lsp-rename-provider.h"
#include "ide-lsp-search-provider.h"
#include "ide-lsp-service.h"
diff --git a/src/libide/lsp/meson.build b/src/libide/lsp/meson.build
index f623287d5..0073aa457 100644
--- a/src/libide/lsp/meson.build
+++ b/src/libide/lsp/meson.build
@@ -19,6 +19,7 @@ libide_lsp_public_headers = [
'ide-lsp-formatter.h',
'ide-lsp-highlighter.h',
'ide-lsp-hover-provider.h',
+ 'ide-lsp-plugin.h',
'ide-lsp-rename-provider.h',
'ide-lsp-search-provider.h',
'ide-lsp-service.h',
@@ -31,6 +32,7 @@ libide_lsp_public_headers = [
]
libide_lsp_private_headers = [
+ 'ide-lsp-plugin-private.h',
'ide-lsp-symbol-node-private.h',
'ide-lsp-symbol-tree-private.h',
]
@@ -53,6 +55,15 @@ libide_lsp_public_sources = [
'ide-lsp-formatter.c',
'ide-lsp-highlighter.c',
'ide-lsp-hover-provider.c',
+ 'ide-lsp-plugin.c',
+ 'ide-lsp-plugin-code-action-provider.c',
+ 'ide-lsp-plugin-completion-provider.c',
+ 'ide-lsp-plugin-diagnostic-provider.c',
+ 'ide-lsp-plugin-formatter.c',
+ 'ide-lsp-plugin-highlighter.c',
+ 'ide-lsp-plugin-hover-provider.c',
+ 'ide-lsp-plugin-rename-provider.c',
+ 'ide-lsp-plugin-symbol-resolver.c',
'ide-lsp-rename-provider.c',
'ide-lsp-search-provider.c',
'ide-lsp-search-result.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]