[gnome-builder/wip/chergert/gjs-in-c] wip




commit 55ada0f5e0fa7819adc849d4f986a8d31afc8934
Author: Christian Hergert <chergert redhat com>
Date:   Mon Apr 25 14:24:20 2022 -0700

    wip

 src/plugins/gjs-symbols/gbp-gjs-code-indexer.c     |  50 +++
 src/plugins/gjs-symbols/gbp-gjs-code-indexer.h     |  31 ++
 src/plugins/gjs-symbols/gbp-gjs-symbol-node.c      | 420 +++++++++++++++++++++
 src/plugins/gjs-symbols/gbp-gjs-symbol-node.h      |  38 ++
 src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.c  | 207 ++++++++++
 src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.h  |  31 ++
 src/plugins/gjs-symbols/gbp-gjs-symbol-tree.c      | 110 ++++++
 src/plugins/gjs-symbols/gbp-gjs-symbol-tree.h      |  33 ++
 src/plugins/gjs-symbols/gjs-symbols-plugin.c       |  41 ++
 src/plugins/gjs-symbols/gjs-symbols.gresource.xml  |   7 +
 .../{gjs_symbols.plugin => gjs-symbols.plugin}     |   7 +-
 src/plugins/gjs-symbols/gjs_symbols.py             | 129 +++----
 src/plugins/gjs-symbols/meson.build                |  22 +-
 src/plugins/gjs-symbols/parse.js                   |  14 +
 14 files changed, 1051 insertions(+), 89 deletions(-)
---
diff --git a/src/plugins/gjs-symbols/gbp-gjs-code-indexer.c b/src/plugins/gjs-symbols/gbp-gjs-code-indexer.c
new file mode 100644
index 000000000..eeb491875
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-code-indexer.c
@@ -0,0 +1,50 @@
+/* gbp-gjs-code-indexer.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 "gbp-gjs-code-indexer"
+
+#include "config.h"
+
+#include <libide-code.h>
+
+#include "gbp-gjs-code-indexer.h"
+
+struct _GbpGjsCodeIndexer
+{
+  IdeObject parent_instance;
+};
+
+static void
+code_indexer_iface_init (IdeCodeIndexerInterface *iface)
+{
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpGjsCodeIndexer, gbp_gjs_code_indexer, IDE_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_CODE_INDEXER, code_indexer_iface_init))
+
+static void
+gbp_gjs_code_indexer_class_init (GbpGjsCodeIndexerClass *klass)
+{
+}
+
+static void
+gbp_gjs_code_indexer_init (GbpGjsCodeIndexer *self)
+{
+}
diff --git a/src/plugins/gjs-symbols/gbp-gjs-code-indexer.h b/src/plugins/gjs-symbols/gbp-gjs-code-indexer.h
new file mode 100644
index 000000000..f8a4356fc
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-code-indexer.h
@@ -0,0 +1,31 @@
+/* gbp-gjs-code-indexer.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 <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GJS_CODE_INDEXER (gbp_gjs_code_indexer_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGjsCodeIndexer, gbp_gjs_code_indexer, GBP, GJS_CODE_INDEXER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-node.c b/src/plugins/gjs-symbols/gbp-gjs-symbol-node.c
new file mode 100644
index 000000000..d095eb1ef
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-node.c
@@ -0,0 +1,420 @@
+/* gbp-gjs-symbol-node.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 "gbp-gjs-symbol-node"
+
+#include "config.h"
+
+#include "gbp-gjs-symbol-node.h"
+
+struct _GbpGjsSymbolNode
+{
+  IdeSymbolNode parent_instance;
+
+  GPtrArray *children;
+
+  guint line;
+  guint line_offset;
+};
+
+G_DEFINE_FINAL_TYPE (GbpGjsSymbolNode, gbp_gjs_symbol_node, IDE_TYPE_SYMBOL_NODE)
+
+static void
+gbp_gjs_symbol_node_dispose (GObject *object)
+{
+  GbpGjsSymbolNode *self = (GbpGjsSymbolNode *)object;
+
+  g_clear_pointer (&self->children, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (gbp_gjs_symbol_node_parent_class)->dispose (object);
+}
+
+static void
+gbp_gjs_symbol_node_class_init (GbpGjsSymbolNodeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gbp_gjs_symbol_node_dispose;
+}
+
+static void
+gbp_gjs_symbol_node_init (GbpGjsSymbolNode *self)
+{
+}
+
+G_GNUC_NULL_TERMINATED
+static JsonNode *
+get_node_at_path (JsonObject *object,
+                  const char *first_child,
+                  ...)
+{
+  const char *child = first_child;
+  JsonNode *ret = NULL;
+  va_list args;
+
+  va_start (args, first_child);
+  while (child != NULL)
+    {
+      JsonNode *node = json_object_get_member (object, child);
+      child = va_arg (args, const char *);
+
+      if (node == NULL)
+        break;
+
+      if (child == NULL && node != NULL)
+        {
+          ret = node;
+          break;
+        }
+
+      if (!JSON_NODE_HOLDS_OBJECT (node))
+        break;
+
+      object = json_node_get_object (node);
+    }
+  va_end (args);
+
+  return ret;
+}
+
+static gboolean
+get_line_and_column (JsonObject *object,
+                     guint      *line,
+                     guint      *column)
+{
+  JsonNode *node;
+
+  g_assert (object != NULL);
+  g_assert (line != NULL);
+  g_assert (column != NULL);
+
+  if (!(node = get_node_at_path (object, "loc", "start", "line", NULL)))
+    return FALSE;
+  *line = MAX (1, json_node_get_int (node)) - 1;
+
+  if (!(node = get_node_at_path (object, "loc", "start", "column", NULL)))
+    return FALSE;
+  *column = MAX (0, json_node_get_int (node));
+
+  return TRUE;
+}
+
+static gboolean
+string_equal_to_node_value (const char *string,
+                            JsonNode   *node)
+{
+  const char *value;
+
+  if (node == NULL || !JSON_NODE_HOLDS_VALUE (node))
+    return FALSE;
+
+  if (!(value = json_node_get_string (node)))
+    return FALSE;
+
+  return g_strcmp0 (string, value) == 0;
+}
+
+static const char *
+get_node_string (JsonNode *node)
+{
+  if (node == NULL || !JSON_NODE_HOLDS_VALUE (node))
+    return NULL;
+  return json_node_get_string (node);
+}
+
+static gboolean
+is_module_import (JsonObject *object)
+{
+  if (object == NULL)
+    return FALSE;
+
+  return string_equal_to_node_value ("imports",
+                                     get_node_at_path (object, "init", "object", "name", NULL)) ||
+         string_equal_to_node_value ("imports",
+                                     get_node_at_path (object, "init", "object", "object", "name", NULL)) ||
+         string_equal_to_node_value ("require",
+                                     get_node_at_path (object, "init", "callee", "name", NULL));
+}
+
+static gboolean
+is_gobject_class (JsonObject *object)
+{
+  const char *name;
+  const char *pname;
+
+  if (object == NULL)
+    return FALSE;
+
+  if (!(name = get_node_string (get_node_at_path (object, "init", "callee", "object", "name", NULL))) ||
+      !(pname = get_node_string (get_node_at_path (object, "init", "callee", "property", "name", NULL))))
+    return FALSE;
+
+  return strcasecmp (name, "gobject") == 0 && ide_str_equal0 (pname, "registerClass");
+}
+
+static gboolean
+is_legacy_gobject_class (JsonObject *object)
+{
+  const char *name;
+  const char *pname;
+
+  if (object == NULL)
+    return FALSE;
+
+  if (!(name = get_node_string (get_node_at_path (object, "init", "callee", "object", "name", NULL))) ||
+      !(pname = get_node_string (get_node_at_path (object, "init", "callee", "property", "name", NULL))))
+    return FALSE;
+
+  return (strcasecmp (name, "gobject") == 0 ||
+          strcasecmp (name, "lang") == 0) &&
+         ide_str_equal0 (pname, "Class");
+}
+
+static gboolean
+is_module_exports (JsonObject *object)
+{
+  JsonNode *left;
+
+  if (object == NULL)
+    return FALSE;
+
+  if (!string_equal_to_node_value ("AssignmentExpression",
+                                   get_node_at_path (object, "expression", "type", NULL)))
+    return FALSE;
+
+  if (!(left = get_node_at_path (object, "expression", "left", NULL)))
+    return FALSE;
+
+  if (!string_equal_to_node_value ("MemberExpression",
+                                   get_node_at_path (object, "expression", "left", "type", NULL)))
+    return FALSE;
+
+  if (!string_equal_to_node_value ("Identifiier",
+                                   get_node_at_path (object, "expression", "left", "object", "type", NULL)))
+    return FALSE;
+
+  if (!string_equal_to_node_value ("module",
+                                   get_node_at_path (object, "expression", "left", "object", "name", NULL)))
+    return FALSE;
+
+  if (!string_equal_to_node_value ("Identifiier",
+                                   get_node_at_path (object, "expression", "left", "property", "type", 
NULL)))
+    return FALSE;
+
+  if (!string_equal_to_node_value ("exports",
+                                   get_node_at_path (object, "expression", "left", "property", "name", 
NULL)))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+gbp_gjs_symbol_node_extract (GbpGjsSymbolNode *self,
+                             JsonObject       *object)
+{
+  IdeSymbolKind kind = IDE_SYMBOL_KIND_NONE;
+  const char *name = NULL;
+  const char *type;
+  JsonNode *body = NULL;
+
+  g_assert (GBP_IS_GJS_SYMBOL_NODE (self));
+  g_assert (object != NULL);
+
+  if (!(type = json_object_get_string_member (object, "type")))
+    return FALSE;
+
+  if (!get_line_and_column (object, &self->line, &self->line_offset))
+    return FALSE;
+
+  self->children = g_ptr_array_new_with_free_func (g_object_unref);
+
+  if (0) {}
+  else if (g_str_equal (type, "Program"))
+    {
+      kind = IDE_SYMBOL_KIND_PACKAGE;
+      name = get_node_string (get_node_at_path (object, "loc", "source", NULL));
+    }
+  else if (g_str_equal (type, "FunctionDeclaration"))
+    {
+      kind = IDE_SYMBOL_KIND_FUNCTION;
+      name = get_node_string (get_node_at_path (object, "id", "name", NULL));
+    }
+  else if (g_str_equal (type, "Property"))
+    {
+      const char *propkind;
+
+      if (!string_equal_to_node_value ("FunctionExpression",
+                                       get_node_at_path (object, "value", "type", NULL)))
+        return FALSE;
+
+      kind = IDE_SYMBOL_KIND_METHOD;
+      name = get_node_string (get_node_at_path (object, "key", "name", NULL));
+      propkind = get_node_string (get_node_at_path (object, "kind", NULL));
+
+      if (ide_str_equal0 (name, "_init") ||
+          ide_str_equal0 (propkind, "get") ||
+          ide_str_equal0 (propkind, "set"))
+        return FALSE;
+
+    }
+  else if (g_str_equal (type, "VariableDeclaration"))
+    {
+      JsonArray *decls_ar;
+      JsonNode *decls;
+      guint n_decls;
+
+      if (!(decls = get_node_at_path (object, "declarations", NULL)) ||
+          !JSON_NODE_HOLDS_ARRAY (decls) ||
+          !(decls_ar = json_node_get_array (decls)) ||
+          !(n_decls = json_array_get_length (decls_ar)))
+        return FALSE;
+
+      for (guint i = 0; i < n_decls; i++)
+        {
+          JsonNode *decl;
+          JsonObject *decl_obj;
+
+          if (!(decl = json_array_get_element (decls_ar, i)) ||
+              !JSON_NODE_HOLDS_OBJECT (decl) ||
+              !(decl_obj = json_node_get_object (decl)))
+            continue;
+
+          if (!string_equal_to_node_value ("Identifier",
+                                           get_node_at_path (decl_obj, "id", "type", NULL)))
+            continue;
+
+          name = get_node_string (get_node_at_path (decl_obj, "id", "name", NULL));
+          kind = IDE_SYMBOL_KIND_VARIABLE;
+
+          if (is_module_import (decl_obj))
+            kind = IDE_SYMBOL_KIND_MODULE;
+        }
+    }
+  else if (g_str_equal (type, "ClassStatement"))
+    {
+      kind = IDE_SYMBOL_KIND_CLASS;
+      name = get_node_string (get_node_at_path (object, "id", "name", NULL));
+      body = get_node_at_path (object, "body", NULL);
+    }
+  else if (g_str_equal (type, "ClassMethod"))
+    {
+      const char *classkind;
+
+      kind = IDE_SYMBOL_KIND_METHOD;
+      name = get_node_string (get_node_at_path (object, "name", "name", NULL));
+      classkind = get_node_string (get_node_at_path (object, "kind", NULL));
+
+      if (ide_str_equal0 (name, "constructed") ||
+          ide_str_equal0 (name, "_init") ||
+          ide_str_equal0 (classkind, "get") ||
+          ide_str_equal0 (classkind, "set"))
+        return FALSE;
+    }
+  else if (g_str_equal (type, "ExpressionStatement"))
+    {
+      JsonNode *right;
+      JsonObject *class;
+
+      if (!string_equal_to_node_value ("ClassExpression",
+                                       get_node_at_path (object, "expression", "right", "type", NULL)))
+        return FALSE;
+
+      if (!(right = get_node_at_path (object, "expression", "right", NULL)) ||
+          !JSON_NODE_HOLDS_OBJECT (right) ||
+          !(class = json_node_get_object (right)))
+        return FALSE;
+
+      if (!get_line_and_column (class, &self->line, &self->line_offset))
+        return FALSE;
+
+      body = get_node_at_path (class, "body", NULL);
+      name = get_node_string (get_node_at_path (class, "id", "name", NULL));
+      kind = IDE_SYMBOL_KIND_CLASS;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+  g_object_set (self,
+                "kind", kind,
+                "name", name,
+                NULL);
+
+  if (body != NULL && JSON_NODE_HOLDS_ARRAY (body))
+    {
+      JsonArray *ar = json_node_get_array (body);
+      guint n_items = json_array_get_length (ar);
+
+      for (guint i = 0; i < n_items; i++)
+        {
+          g_autoptr(GbpGjsSymbolNode) symbol_node = NULL;
+          JsonNode *child_node = json_array_get_element (ar, i);
+
+          if (!JSON_NODE_HOLDS_OBJECT (child_node) ||
+              !(symbol_node = gbp_gjs_symbol_node_new (object)))
+            continue;
+
+          g_ptr_array_add (self->children, g_steal_pointer (&symbol_node));
+        }
+    }
+
+  if (self->children->len == 0)
+    g_clear_pointer (&self->children, g_ptr_array_unref);
+
+  return TRUE;
+}
+
+GbpGjsSymbolNode *
+gbp_gjs_symbol_node_new (JsonObject *object)
+{
+  g_autoptr(GbpGjsSymbolNode) self = NULL;
+
+  g_return_val_if_fail (object != NULL, NULL);
+
+  self = g_object_new (GBP_TYPE_GJS_SYMBOL_NODE, NULL);
+  if (!gbp_gjs_symbol_node_extract (self, object))
+    return NULL;
+
+  return g_steal_pointer (&self);
+}
+
+guint
+gbp_gjs_symbol_node_get_n_children (GbpGjsSymbolNode *self)
+{
+  g_return_val_if_fail (GBP_IS_GJS_SYMBOL_NODE (self), 0);
+
+  if (self->children == NULL)
+    return 0;
+
+  return self->children->len;
+}
+
+IdeSymbolNode *
+gbp_gjs_symbol_node_get_nth_child (GbpGjsSymbolNode *self,
+                                   guint             nth_child)
+{
+  g_return_val_if_fail (GBP_IS_GJS_SYMBOL_NODE (self), NULL);
+
+  if (self->children == NULL || nth_child >= self->children->len)
+    return NULL;
+
+  return g_object_ref (g_ptr_array_index (self->children, nth_child));
+}
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-node.h b/src/plugins/gjs-symbols/gbp-gjs-symbol-node.h
new file mode 100644
index 000000000..36731e488
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-node.h
@@ -0,0 +1,38 @@
+/* gbp-gjs-symbol-node.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 <json-glib/json-glib.h>
+
+#include <libide-code.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GJS_SYMBOL_NODE (gbp_gjs_symbol_node_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGjsSymbolNode, gbp_gjs_symbol_node, GBP, GJS_SYMBOL_NODE, IdeSymbolNode)
+
+GbpGjsSymbolNode *gbp_gjs_symbol_node_new            (JsonObject       *object);
+guint             gbp_gjs_symbol_node_get_n_children (GbpGjsSymbolNode *self);
+IdeSymbolNode    *gbp_gjs_symbol_node_get_nth_child  (GbpGjsSymbolNode *self,
+                                                      guint             nth_child);
+
+G_END_DECLS
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.c 
b/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.c
new file mode 100644
index 000000000..eda8ae68e
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.c
@@ -0,0 +1,207 @@
+/* gbp-gjs-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 "gbp-gjs-symbol-resolver"
+
+#include "config.h"
+
+#include <errno.h>
+#include <json-glib/json-glib.h>
+#include <unistd.h>
+
+#include <libide-code.h>
+#include <libide-foundry.h>
+#include <libide-threading.h>
+
+#include "gbp-gjs-symbol-resolver.h"
+#include "gbp-gjs-symbol-tree.h"
+
+struct _GbpGjsSymbolResolver
+{
+  IdeObject parent_instance;
+};
+
+static void
+gbp_gjs_symbol_resolver_get_symbol_tree_cb (GObject      *object,
+                                            GAsyncResult *result,
+                                            gpointer      user_data)
+{
+  IdeSubprocess *subprocess = (IdeSubprocess *)object;
+  g_autoptr(GbpGjsSymbolNode) node = NULL;
+  g_autoptr(JsonParser) parser = NULL;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+  g_autofree char *stdout_buf = NULL;
+  JsonObject *obj;
+  JsonNode *root;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_SUBPROCESS (subprocess));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
+
+  if (!ide_subprocess_communicate_utf8_finish (subprocess, result, &stdout_buf, NULL, &error))
+    {
+      ide_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  parser = json_parser_new ();
+
+  if (!json_parser_load_from_data (parser, stdout_buf, -1, &error))
+    {
+      ide_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  if (!(root = json_parser_get_root (parser)) ||
+      !JSON_NODE_HOLDS_OBJECT (root) ||
+      !(obj = json_node_get_object (root)) ||
+      !(node = gbp_gjs_symbol_node_new (obj)))
+    {
+      ide_task_return_new_error (task,
+                                 G_IO_ERROR,
+                                 G_IO_ERROR_INVALID_DATA,
+                                 "Reflect.parse() returned invalid data");
+      IDE_EXIT;
+    }
+
+  ide_task_return_object (task, gbp_gjs_symbol_tree_new (node));
+
+  IDE_EXIT;
+}
+
+static void
+gbp_gjs_symbol_resolver_get_symbol_tree_async (IdeSymbolResolver   *resolver,
+                                               GFile               *file,
+                                               GBytes              *contents,
+                                               GCancellable        *cancellable,
+                                               GAsyncReadyCallback  callback,
+                                               gpointer             user_data)
+{
+  g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+  g_autoptr(IdeSubprocess) subprocess = NULL;
+  g_autoptr(IdeContext) context = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autoptr(GBytes) script = NULL;
+  g_autoptr(IdeTask) task = NULL;
+  g_autofree char *name = NULL;
+  int fd;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_GJS_SYMBOL_RESOLVER (resolver));
+  g_assert (G_IS_FILE (file));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (resolver, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, gbp_gjs_symbol_resolver_get_symbol_tree_async);
+
+  script = g_resources_lookup_data ("/plugins/gjs-symbols/parse.js", 0, NULL);
+  name = g_file_get_basename (file);
+
+  g_assert (script != NULL);
+  g_assert (name != NULL);
+
+  if (!(context = ide_object_ref_context (IDE_OBJECT (resolver))) ||
+      !(launcher = ide_foundry_get_launcher_for_context (context, "gjs", "/usr/bin/gjs", NULL)))
+    {
+      ide_task_return_new_error (task,
+                                 G_IO_ERROR,
+                                 G_IO_ERROR_NOT_SUPPORTED,
+                                 "A working `gjs` could not be found");
+      IDE_EXIT;
+    }
+
+  if (contents != NULL)
+    fd = ide_foundry_bytes_to_memfd (contents, "gjs-symbols-data");
+  else
+    fd = ide_foundry_file_to_memfd (file, "gjs-symbols-data");
+
+  if (fd < 0)
+    {
+      ide_task_return_new_error (task,
+                                 G_IO_ERROR,
+                                 G_IO_ERROR_FAILED,
+                                 "Failed to open temporary file: %s",
+                                 g_strerror (errno));
+      IDE_EXIT;
+    }
+
+  ide_subprocess_launcher_set_flags (launcher,
+                                     (G_SUBPROCESS_FLAGS_STDOUT_PIPE |
+                                      G_SUBPROCESS_FLAGS_STDERR_SILENCE));
+  ide_subprocess_launcher_take_fd (launcher, fd, 3);
+  ide_subprocess_launcher_push_argv (launcher, "-c");
+  ide_subprocess_launcher_push_argv (launcher, (const char *)g_bytes_get_data (script, NULL));
+  ide_subprocess_launcher_push_argv (launcher, name);
+
+  if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
+    {
+      ide_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  ide_subprocess_communicate_utf8_async (subprocess,
+                                         NULL,
+                                         cancellable,
+                                         gbp_gjs_symbol_resolver_get_symbol_tree_cb,
+                                         g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+static IdeSymbolTree *
+gbp_gjs_symbol_resolver_get_symbol_tree_finish (IdeSymbolResolver  *resolver,
+                                                GAsyncResult       *result,
+                                                GError            **error)
+{
+  IdeSymbolTree *ret;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_GJS_SYMBOL_RESOLVER (resolver));
+  g_assert (IDE_IS_TASK (result));
+
+  ret = ide_task_propagate_object (IDE_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+symbol_resolver_iface_init (IdeSymbolResolverInterface *iface)
+{
+  iface->get_symbol_tree_async = gbp_gjs_symbol_resolver_get_symbol_tree_async;
+  iface->get_symbol_tree_finish = gbp_gjs_symbol_resolver_get_symbol_tree_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpGjsSymbolResolver, gbp_gjs_symbol_resolver, G_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_SYMBOL_RESOLVER, symbol_resolver_iface_init))
+
+static void
+gbp_gjs_symbol_resolver_class_init (GbpGjsSymbolResolverClass *klass)
+{
+}
+
+static void
+gbp_gjs_symbol_resolver_init (GbpGjsSymbolResolver *self)
+{
+}
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.h 
b/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.h
new file mode 100644
index 000000000..4e7f8e618
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-resolver.h
@@ -0,0 +1,31 @@
+/* gbp-gjs-symbol-resolver.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 <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GJS_SYMBOL_RESOLVER (gbp_gjs_symbol_resolver_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGjsSymbolResolver, gbp_gjs_symbol_resolver, GBP, GJS_SYMBOL_RESOLVER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.c b/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.c
new file mode 100644
index 000000000..4b36d9738
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.c
@@ -0,0 +1,110 @@
+/* gbp-gjs-symbol-tree.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 "gbp-gjs-symbol-tree"
+
+#include "config.h"
+
+#include <libide-code.h>
+
+#include "gbp-gjs-symbol-tree.h"
+
+struct _GbpGjsSymbolTree
+{
+  GObject           parent_instance;
+  GbpGjsSymbolNode *root;
+};
+
+static guint
+gbp_gjs_symbol_tree_get_n_children (IdeSymbolTree *tree,
+                                    IdeSymbolNode *node)
+{
+  GbpGjsSymbolTree *self = (GbpGjsSymbolTree *)tree;
+
+  g_assert (GBP_IS_GJS_SYMBOL_TREE (self));
+  g_assert (!node || GBP_IS_GJS_SYMBOL_NODE (node));
+
+  if (node == NULL)
+    return gbp_gjs_symbol_node_get_n_children (self->root);
+  else
+    return gbp_gjs_symbol_node_get_n_children (GBP_GJS_SYMBOL_NODE (node));
+}
+
+static IdeSymbolNode *
+gbp_gjs_symbol_tree_get_nth_child (IdeSymbolTree *tree,
+                                   IdeSymbolNode *node,
+                                   guint          nth_child)
+{
+  GbpGjsSymbolTree *self = (GbpGjsSymbolTree *)tree;
+
+  g_assert (GBP_IS_GJS_SYMBOL_TREE (self));
+  g_assert (!node || GBP_IS_GJS_SYMBOL_NODE (node));
+
+  if (node == NULL)
+    return gbp_gjs_symbol_node_get_nth_child (self->root, nth_child);
+  else
+    return gbp_gjs_symbol_node_get_nth_child (GBP_GJS_SYMBOL_NODE (node), nth_child);
+}
+
+static void
+symbol_tree_iface_init (IdeSymbolTreeInterface *iface)
+{
+  iface->get_n_children = gbp_gjs_symbol_tree_get_n_children;
+  iface->get_nth_child = gbp_gjs_symbol_tree_get_nth_child;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpGjsSymbolTree, gbp_gjs_symbol_tree, G_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_SYMBOL_TREE, symbol_tree_iface_init))
+
+static void
+gbp_gjs_symbol_tree_finalize (GObject *object)
+{
+  GbpGjsSymbolTree *self = (GbpGjsSymbolTree *)object;
+
+  g_clear_object (&self->root);
+
+  G_OBJECT_CLASS (gbp_gjs_symbol_tree_parent_class)->finalize (object);
+}
+
+static void
+gbp_gjs_symbol_tree_class_init (GbpGjsSymbolTreeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gbp_gjs_symbol_tree_finalize;
+}
+
+static void
+gbp_gjs_symbol_tree_init (GbpGjsSymbolTree *self)
+{
+}
+
+GbpGjsSymbolTree *
+gbp_gjs_symbol_tree_new (GbpGjsSymbolNode *root)
+{
+  GbpGjsSymbolTree *self;
+
+  g_return_val_if_fail (GBP_IS_GJS_SYMBOL_NODE (root), NULL);
+
+  self = g_object_new (GBP_TYPE_GJS_SYMBOL_TREE, NULL);
+  self->root = g_object_ref (root);
+
+  return self;
+}
diff --git a/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.h b/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.h
new file mode 100644
index 000000000..b6fb38544
--- /dev/null
+++ b/src/plugins/gjs-symbols/gbp-gjs-symbol-tree.h
@@ -0,0 +1,33 @@
+/* gbp-gjs-symbol-tree.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 "gbp-gjs-symbol-node.h"
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GJS_SYMBOL_TREE (gbp_gjs_symbol_tree_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGjsSymbolTree, gbp_gjs_symbol_tree, GBP, GJS_SYMBOL_TREE, GObject)
+
+GbpGjsSymbolTree *gbp_gjs_symbol_tree_new (GbpGjsSymbolNode *root);
+
+G_END_DECLS
diff --git a/src/plugins/gjs-symbols/gjs-symbols-plugin.c b/src/plugins/gjs-symbols/gjs-symbols-plugin.c
new file mode 100644
index 000000000..b9d6d5be0
--- /dev/null
+++ b/src/plugins/gjs-symbols/gjs-symbols-plugin.c
@@ -0,0 +1,41 @@
+/* gjs-symbols-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 "gjs-symbols-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-code.h>
+
+#include "gbp-gjs-code-indexer.h"
+#include "gbp-gjs-symbol-resolver.h"
+
+_IDE_EXTERN void
+_gbp_gjs_symbols_register_types (PeasObjectModule *module)
+{
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_SYMBOL_RESOLVER,
+                                              GBP_TYPE_GJS_SYMBOL_RESOLVER);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_CODE_INDEXER,
+                                              GBP_TYPE_GJS_CODE_INDEXER);
+}
diff --git a/src/plugins/gjs-symbols/gjs-symbols.gresource.xml 
b/src/plugins/gjs-symbols/gjs-symbols.gresource.xml
new file mode 100644
index 000000000..3d773032c
--- /dev/null
+++ b/src/plugins/gjs-symbols/gjs-symbols.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/plugins/gjs-symbols">
+    <file>gjs-symbols.plugin</file>
+    <file>parse.js</file>
+  </gresource>
+</gresources>
diff --git a/src/plugins/gjs-symbols/gjs_symbols.plugin b/src/plugins/gjs-symbols/gjs-symbols.plugin
similarity index 67%
rename from src/plugins/gjs-symbols/gjs_symbols.plugin
rename to src/plugins/gjs-symbols/gjs-symbols.plugin
index c715af17c..ff9aba2c9 100644
--- a/src/plugins/gjs-symbols/gjs_symbols.plugin
+++ b/src/plugins/gjs-symbols/gjs-symbols.plugin
@@ -1,13 +1,12 @@
 [Plugin]
 Authors=Patrick Griffis <tingping tingping se>
 Builtin=true
-Copyright=Copyright © 2017 Patrick Griffis
+Copyright=Copyright © 2017 Patrick Griffis, Copyright © 2022 Christian Hergert
 Description=Provides a symbol resolver for JavaScript using GJS.
-Loader=python3
-Module=gjs_symbols
+Embedded=_gbp_gjs_symbol_register_types
+Module=gjs-symbols
 Name=GJS Symbol Resolver
 X-Code-Indexer-Languages-Priority=0
 X-Code-Indexer-Languages=js
 X-Symbol-Resolver-Languages-Priority=0
 X-Symbol-Resolver-Languages=js
-X-Builder-ABI=@PACKAGE_ABI@
diff --git a/src/plugins/gjs-symbols/gjs_symbols.py b/src/plugins/gjs-symbols/gjs_symbols.py
index e06353f3c..16b31c785 100644
--- a/src/plugins/gjs-symbols/gjs_symbols.py
+++ b/src/plugins/gjs-symbols/gjs_symbols.py
@@ -43,7 +43,7 @@ class JsSymbolNode(Ide.SymbolNode):
         self.children = children
 
     def do_get_location_async(self, cancellable, callback, user_data=None):
-        task = Gio.Task.new(self, cancellable, callback)
+        task = Ide.Task.new(self, cancellable, callback)
         task.return_boolean(True)
 
     def do_get_location_finish(self, result):
@@ -251,98 +251,73 @@ try {
         data = ARGV[0];
     }
     print(JSON.stringify(Reflect.parse(data, {source: '%s'})));
+
+    subprocess =
 } catch (e) {
     imports.system.exit(1);
 }
 """.replace('\n', ' ')
 
+def _get_launcher(context, file_):
+    file_path = file_.get_path()
+    script = JS_SCRIPT % file_path.replace('\\', '\\\\').replace("'", "\\'")
+    unsaved_file = Ide.UnsavedFiles.from_context(context).get_unsaved_file(file_)
+    srcdir = context.ref_workdir().get_path()
+    launcher = None
 
-class GjsSymbolProvider(Ide.Object, Ide.SymbolResolver):
-    def __init__(self):
-        super().__init__()
+    if context.has_project():
+        pipeline = Ide.BuildManager.from_context(context).get_pipeline()
+        if pipeline is not None and pipeline.contains_program_in_path('gjs'):
+            launcher = pipeline.create_launcher()
+            srcdir = pipeline.get_srcdir()
 
-    @staticmethod
-    def _get_launcher(context, file_):
-        file_path = file_.get_path()
-        script = JS_SCRIPT % file_path.replace('\\', '\\\\').replace("'", "\\'")
-        unsaved_file = Ide.UnsavedFiles.from_context(context).get_unsaved_file(file_)
-        srcdir = context.ref_workdir().get_path()
-        launcher = None
-
-        if context.has_project():
-            pipeline = Ide.BuildManager.from_context(context).get_pipeline()
-            if pipeline is not None and pipeline.contains_program_in_path('gjs'):
-                launcher = pipeline.create_launcher()
-                srcdir = pipeline.get_srcdir()
-
-        if launcher is None:
-            launcher = Ide.SubprocessLauncher.new(0)
-
-        launcher.set_cwd(srcdir)
-        launcher.set_flags(Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_SILENCE)
-        launcher.push_args(('gjs', '-c', script))
-
-        if unsaved_file is not None:
-            launcher.push_argv(unsaved_file.get_content().get_data().decode('utf-8'))
-        else:
-            launcher.push_args(('--file', file_path))
+    if launcher is None:
+        launcher = Ide.SubprocessLauncher.new(0)
 
-        return launcher
+    launcher.set_cwd(srcdir)
+    launcher.set_flags(Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_SILENCE)
+    launcher.push_args(('gjs', '-c', script))
 
-    def do_lookup_symbol_async(self, location, cancellable, callback, user_data=None):
-        task = Gio.Task.new(self, cancellable, callback)
-        task.return_error(GLib.Error('Not implemented'))
+    if unsaved_file is not None:
+        launcher.push_argv(unsaved_file.get_content().get_data().decode('utf-8'))
+    else:
+        launcher.push_args(('--file', file_path))
 
-    def do_lookup_symbol_finish(self, result):
-        result.propagate_boolean()
-        return None
-
-    def do_get_symbol_tree_async(self, file_, buffer_, cancellable, callback, user_data=None):
-        task = Gio.Task.new(self, cancellable, callback)
-        launcher = self._get_launcher(self.get_context(), file_)
+    return launcher
 
-        threading.Thread(target=self._get_tree_thread, args=(task, launcher, file_),
-                         name='gjs-symbols-thread').start()
+def _get_tree_thread(task, launcher, file_):
+    try:
+        proc = launcher.spawn()
+        success, stdout, stderr = proc.communicate_utf8(None, None)
 
-    def _get_tree_thread(self, task, launcher, file_):
-        try:
-            proc = launcher.spawn()
-            success, stdout, stderr = proc.communicate_utf8(None, None)
-
-            if not success:
-                task.return_error(GLib.Error('Failed to run gjs'))
-                return
-
-            task.symbol_tree = JsSymbolTree(json.loads(stdout), file_)
-        except GLib.Error as err:
-            task.return_error(err)
-        except (json.JSONDecodeError, UnicodeDecodeError) as e:
-            task.return_error(GLib.Error('Failed to decode gjs json: {}'.format(e)))
-        except (IndexError, KeyError) as e:
-            task.return_error(GLib.Error('Failed to extract information from ast: {}'.format(e)))
-        else:
-            task.return_boolean(True)
+        if not success:
+            task.return_error(GLib.Error('Failed to run gjs'))
+            return
 
-    def do_get_symbol_tree_finish(self, result):
-        if result.propagate_boolean():
-            return result.symbol_tree
+        task.symbol_tree = JsSymbolTree(json.loads(stdout), file_)
+    except GLib.Error as err:
+        task.return_error(err)
+    except (json.JSONDecodeError, UnicodeDecodeError) as e:
+        task.return_error(GLib.Error('Failed to decode gjs json: {}'.format(e)))
+    except (IndexError, KeyError) as e:
+        task.return_error(GLib.Error('Failed to extract information from ast: {}'.format(e)))
+    else:
+        task.return_boolean(True)
 
-    def do_load(self):
-        pass
 
-    def do_find_references_async(self, location, language_id, cancellable, callback, user_data=None):
-        task = Gio.Task.new(self, cancellable, callback)
-        task.return_error(GLib.Error('Not implemented'))
+class GjsSymbolProvider(Ide.Object, Ide.SymbolResolver):
 
-    def do_find_references_finish(self, result):
-        return result.propagate_boolean()
+    def do_get_symbol_tree_async(self, file_, buffer_, cancellable, callback, data):
+        task = Ide.Task.new(self, cancellable, callback)
+        launcher = _get_launcher(self.get_context(), file_)
 
-    def do_find_nearest_scope_async(self, location, cancellable, callback, user_data=None):
-        task = Gio.Task.new(self, cancellable, callback)
-        task.return_error(GLib.Error('Not implemented'))
+        threading.Thread(target=_get_tree_thread,
+                         args=(task, launcher, file_),
+                         name='gjs-symbols-thread').start()
 
-    def do_find_nearest_scope_finish(self, result):
-        return result.propagate_boolean()
+    def do_get_symbol_tree_finish(self, result):
+        if result.propagate_boolean():
+            return result.symbol_tree
 
 
 class JsCodeIndexEntries(GObject.Object, Ide.CodeIndexEntries):
@@ -435,7 +410,7 @@ class GjsCodeIndexer(Ide.Object, Ide.CodeIndexer):
             self.active = False
 
     def do_index_file_async(self, file_, build_flags, cancellable, callback, data):
-        task = Gio.Task.new(self, cancellable, callback)
+        task = Ide.Task.new(self, cancellable, callback)
         task.entries = None
         task.file = file_
 
@@ -455,7 +430,7 @@ class GjsCodeIndexer(Ide.Object, Ide.CodeIndexer):
 
     def do_generate_key_async(self, location, flags, cancellable, callback, user_data=None):
         # print('generate key')
-        task = Gio.Task.new(self, cancellable, callback)
+        task = Ide.Task.new(self, cancellable, callback)
         task.return_error(GLib.Error('Not implemented'))
 
     def do_generate_key_finish(self, result):
diff --git a/src/plugins/gjs-symbols/meson.build b/src/plugins/gjs-symbols/meson.build
index 43ccc9724..51d8dae87 100644
--- a/src/plugins/gjs-symbols/meson.build
+++ b/src/plugins/gjs-symbols/meson.build
@@ -1,13 +1,19 @@
 if get_option('plugin_gjs_symbols')
 
-install_data('gjs_symbols.py', install_dir: plugindir)
-
-configure_file(
-          input: 'gjs_symbols.plugin',
-         output: 'gjs_symbols.plugin',
-  configuration: config_h,
-        install: true,
-    install_dir: plugindir,
+plugins_sources += files([
+  'gjs-symbols-plugin.c',
+  'gbp-gjs-symbol-resolver.c',
+  'gbp-gjs-symbol-node.c',
+  'gbp-gjs-symbol-tree.c',
+  'gbp-gjs-code-indexer.c',
+])
+
+plugin_gjs_symbols_resources = gnome.compile_resources(
+  'gjs-symbols-resources',
+  'gjs-symbols.gresource.xml',
+  c_name: 'gbp_gjs_symbols',
 )
 
+plugins_sources += plugin_gjs_symbols_resources
+
 endif
diff --git a/src/plugins/gjs-symbols/parse.js b/src/plugins/gjs-symbols/parse.js
new file mode 100644
index 000000000..4efdc0192
--- /dev/null
+++ b/src/plugins/gjs-symbols/parse.js
@@ -0,0 +1,14 @@
+try {
+    const DATA_FD = 0;
+    const Gio = imports.gi.Gio;
+    const GLib = imports.gi.GLib;
+
+    let input = Gio.UnixInputStream.new(DATA_FD, true);
+    let reader = Gio.DataInputStream.new(input);
+    let [data, len] = reader.read_upto("", -1, null);
+
+    print(JSON.stringify(Reflect.parse(data, {source: ARGV[1]})));
+} catch (e) {
+    print(e);
+    imports.system.exit(1);
+}


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