[gnome-builder] buffer: Use multiple symbol resolvers instead of one.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] buffer: Use multiple symbol resolvers instead of one.
- Date: Fri, 1 Sep 2017 22:25:05 +0000 (UTC)
commit 6f17acdfe9357b03d8e7e635ae60a8a2fcc64293
Author: Anoop Chandu <anoopchandu96 gmail com>
Date: Tue Aug 29 21:15:21 2017 +0530
buffer: Use multiple symbol resolvers instead of one.
With multiple symbol resolvers if any result is not found by one
resolver other symbol resolvers can be tried for getting results.
https://bugzilla.gnome.org/show_bug.cgi?id=786700
libide/buffers/ide-buffer.c | 200 ++++++++++++++------
libide/buffers/ide-buffer.h | 117 ++++++------
libide/plugins/ide-extension-set-adapter.c | 10 +
libide/sourceview/ide-source-view.c | 95 ++++++++--
.../symbol-tree/gbp-symbol-layout-stack-addin.c | 188 +++++++++++++++----
tests/meson.build | 49 ++++--
6 files changed, 481 insertions(+), 178 deletions(-)
---
diff --git a/libide/buffers/ide-buffer.c b/libide/buffers/ide-buffer.c
index be6f9ff..22b49f6 100644
--- a/libide/buffers/ide-buffer.c
+++ b/libide/buffers/ide-buffer.c
@@ -81,7 +81,7 @@ typedef struct
IdeHighlightEngine *highlight_engine;
IdeExtensionAdapter *formatter_adapter;
IdeExtensionAdapter *rename_provider_adapter;
- IdeExtensionAdapter *symbol_resolver_adapter;
+ IdeExtensionSetAdapter *symbol_resolvers_adapter;
PeasExtensionSet *addins;
gchar *title;
@@ -112,6 +112,15 @@ typedef struct
guint read_only : 1;
} IdeBufferPrivate;
+typedef struct
+{
+ GPtrArray *resolvers;
+
+ IdeSourceLocation *location;
+
+ IdeSymbol *symbol;
+} LookUpSymbolData;
+
G_DEFINE_TYPE_WITH_PRIVATE (IdeBuffer, ide_buffer, GTK_SOURCE_TYPE_BUFFER)
DZL_DEFINE_COUNTER (instances, "IdeBuffer", "Instances", "Number of IdeBuffer instances.")
@@ -137,13 +146,33 @@ enum {
LINE_FLAGS_CHANGED,
LOADED,
SAVED,
- SYMBOL_RESOLVER_LOADED,
+ SYMBOL_RESOLVERS_LOADED,
LAST_SIGNAL
};
static GParamSpec *properties [LAST_PROP];
static guint signals [LAST_SIGNAL];
+static void
+lookup_symbol_task_data_free (LookUpSymbolData *data)
+{
+ g_clear_pointer (&data->resolvers, g_ptr_array_unref);
+ g_clear_pointer (&data->location, ide_source_location_unref);
+ g_clear_pointer (&data->symbol, ide_symbol_unref);
+ g_slice_free (LookUpSymbolData, data);
+}
+
+static void
+lookup_symbol_get_extension (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ LookUpSymbolData *data = user_data;
+
+ g_ptr_array_add (data->resolvers, IDE_SYMBOL_RESOLVER (extension));
+}
+
static gboolean
ide_buffer_settled_cb (gpointer user_data)
{
@@ -904,8 +933,8 @@ ide_buffer_notify_language (IdeBuffer *self,
if (priv->rename_provider_adapter != NULL)
ide_extension_adapter_set_value (priv->rename_provider_adapter, lang_id);
- if (priv->symbol_resolver_adapter != NULL)
- ide_extension_adapter_set_value (priv->symbol_resolver_adapter, lang_id);
+ if (priv->symbol_resolvers_adapter != NULL)
+ ide_extension_set_adapter_set_value (priv->symbol_resolvers_adapter, lang_id);
if (priv->formatter_adapter != NULL)
ide_extension_adapter_set_value (priv->formatter_adapter, lang_id);
@@ -1118,24 +1147,31 @@ ide_buffer_load_rename_provider (IdeBuffer *self,
}
static void
-ide_buffer_load_symbol_resolver (IdeBuffer *self,
- GParamSpec *pspec,
- IdeExtensionAdapter *adapter)
+ide_buffer_load_symbol_resolver (IdeExtensionSetAdapter *adapter,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
{
- IdeSymbolResolver *resolver;
+ ide_symbol_resolver_load (IDE_SYMBOL_RESOLVER (extension));
+}
+static void
+ide_buffer_load_symbol_resolvers (IdeBuffer *self,
+ IdeExtensionSetAdapter *adapter)
+{
IDE_ENTRY;
g_assert (IDE_IS_BUFFER (self));
- g_assert (IDE_IS_EXTENSION_ADAPTER (adapter));
+ g_assert (IDE_IS_EXTENSION_SET_ADAPTER (adapter));
- resolver = ide_extension_adapter_get_extension (adapter);
+ if (!ide_extension_set_adapter_get_n_extensions (adapter))
+ return;
- if (resolver != NULL)
- {
- ide_symbol_resolver_load (resolver);
- g_signal_emit (self, signals [SYMBOL_RESOLVER_LOADED], 0);
- }
+ ide_extension_set_adapter_foreach (adapter,
+ ide_buffer_load_symbol_resolver,
+ NULL);
+
+ g_signal_emit (self, signals [SYMBOL_RESOLVERS_LOADED], 0);
IDE_EXIT;
}
@@ -1317,15 +1353,15 @@ ide_buffer_constructed (GObject *object)
self,
G_CONNECT_SWAPPED);
- priv->symbol_resolver_adapter = ide_extension_adapter_new (priv->context,
- NULL,
- IDE_TYPE_SYMBOL_RESOLVER,
- "Symbol-Resolver-Languages",
- NULL);
+ priv->symbol_resolvers_adapter = ide_extension_set_adapter_new (priv->context,
+ peas_engine_get_default (),
+ IDE_TYPE_SYMBOL_RESOLVER,
+ "Symbol-Resolver-Languages",
+ NULL);
- g_signal_connect_object (priv->symbol_resolver_adapter,
- "notify::extension",
- G_CALLBACK (ide_buffer_load_symbol_resolver),
+ g_signal_connect_object (priv->symbol_resolvers_adapter,
+ "extensions-loaded",
+ G_CALLBACK (ide_buffer_load_symbol_resolvers),
self,
G_CONNECT_SWAPPED);
@@ -1388,7 +1424,7 @@ ide_buffer_dispose (GObject *object)
g_clear_object (&priv->addins);
g_clear_object (&priv->highlight_engine);
g_clear_object (&priv->rename_provider_adapter);
- g_clear_object (&priv->symbol_resolver_adapter);
+ g_clear_object (&priv->symbol_resolvers_adapter);
G_OBJECT_CLASS (ide_buffer_parent_class)->dispose (object);
@@ -1680,10 +1716,10 @@ ide_buffer_class_init (IdeBufferClass *klass)
/**
* IdeBuffer::symbol-resolver-loaded:
*
- * This signal is emitted when the buffer has completed loading a new symbol resolver.
+ * This signal is emitted when the buffer has completed loading symbol resolvers.
*/
- signals [SYMBOL_RESOLVER_LOADED] =
- g_signal_new_class_handler ("symbol-resolver-loaded",
+ signals [SYMBOL_RESOLVERS_LOADED] =
+ g_signal_new_class_handler ("symbol-resolvers-loaded",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
@@ -2532,26 +2568,66 @@ ide_buffer_rehighlight (IdeBuffer *self)
}
static void
-ide_buffer__symbol_provider_lookup_symbol_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
+ide_buffer_get_symbol_at_location_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
IdeSymbolResolver *symbol_resolver = (IdeSymbolResolver *)object;
g_autoptr(IdeSymbol) symbol = NULL;
g_autoptr(GTask) task = user_data;
- GError *error = NULL;
+ g_autoptr(GError) error = NULL;
+ LookUpSymbolData *data;
+ g_assert (IDE_IS_SYMBOL_RESOLVER (symbol_resolver));
g_assert (G_IS_TASK (task));
symbol = ide_symbol_resolver_lookup_symbol_finish (symbol_resolver, result, &error);
- if (symbol == NULL)
+ data = g_task_get_task_data (task);
+
+ if (symbol != NULL)
{
- g_task_return_error (task, error);
- return;
+ /*
+ * Store symbol which has definition location. If no symbol has definition location
+ * then store symbol which has declaration location.
+ */
+ if ((data->symbol == NULL) ||
+ (ide_symbol_get_definition_location (symbol) != NULL) ||
+ (ide_symbol_get_definition_location (data->symbol) == NULL &&
+ ide_symbol_get_declaration_location (symbol)))
+ {
+ g_clear_pointer (&data->symbol, ide_symbol_unref);
+
+ data->symbol = g_steal_pointer (&symbol);
+ }
}
- g_task_return_pointer (task, ide_symbol_ref (symbol), (GDestroyNotify)ide_symbol_unref);
+ g_ptr_array_remove_index (data->resolvers, data->resolvers->len - 1);
+
+ if (data->resolvers->len)
+ {
+ IdeSymbolResolver *resolver;
+ GCancellable *cancellable;
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+ cancellable = g_task_get_cancellable (task);
+
+ ide_symbol_resolver_lookup_symbol_async (resolver,
+ data->location,
+ cancellable,
+ ide_buffer_get_symbol_at_location_cb,
+ g_steal_pointer (&task));
+ }
+ else if (data->symbol == NULL)
+ {
+ g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Symbol not found");
+ }
+ else
+ {
+ g_task_return_pointer (task,
+ g_steal_pointer (&data->symbol),
+ (GDestroyNotify)ide_symbol_unref);
+ }
}
/**
@@ -2573,41 +2649,56 @@ ide_buffer_get_symbol_at_location_async (IdeBuffer *self,
gpointer user_data)
{
IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
- IdeSymbolResolver *symbol_resolver;
+ IdeExtensionSetAdapter *adapter;
+ IdeSymbolResolver *resolver;
g_autoptr(GTask) task = NULL;
g_autoptr(IdeSourceLocation) srcloc = NULL;
guint line;
guint line_offset;
guint offset;
+ guint n_extensions;
+ g_autoptr(GPtrArray) extensions = NULL;
+ LookUpSymbolData *data;
g_return_if_fail (IDE_IS_BUFFER (self));
g_return_if_fail (location != NULL);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
- task = g_task_new (self, cancellable, callback, user_data);
-
- symbol_resolver = ide_buffer_get_symbol_resolver (self);
+ adapter = ide_buffer_get_symbol_resolvers (self);
+ n_extensions = ide_extension_set_adapter_get_n_extensions (adapter);
- if (symbol_resolver == NULL)
+ if (!n_extensions)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
- _("The current language lacks a symbol resolver."));
+ _("The current language lacks symbol resolver."));
return;
}
+ task = g_task_new (self, cancellable, callback, user_data);
+
line = gtk_text_iter_get_line (location);
line_offset = gtk_text_iter_get_line_offset (location);
offset = gtk_text_iter_get_offset (location);
-
srcloc = ide_source_location_new (priv->file, line, line_offset, offset);
- ide_symbol_resolver_lookup_symbol_async (symbol_resolver,
- srcloc,
+ data = g_slice_new0 (LookUpSymbolData);
+ data->resolvers = g_ptr_array_new_full (n_extensions, NULL);
+ data->location = ide_source_location_ref (srcloc);
+
+ ide_extension_set_adapter_foreach (adapter, lookup_symbol_get_extension, data);
+
+ g_task_set_task_data (task, data, (GDestroyNotify)lookup_symbol_task_data_free);
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+
+ /* Try lookup_symbol on each symbol resolver one by by one. */
+ ide_symbol_resolver_lookup_symbol_async (resolver,
+ data->location,
cancellable,
- ide_buffer__symbol_provider_lookup_symbol_cb,
- g_object_ref (task));
+ ide_buffer_get_symbol_at_location_cb,
+ g_steal_pointer (&task));
}
/**
@@ -2661,7 +2752,7 @@ ide_buffer_reclaim_timeout (gpointer data)
priv->reclamation_handler = 0;
g_clear_object (&priv->rename_provider_adapter);
- g_clear_object (&priv->symbol_resolver_adapter);
+ g_clear_object (&priv->symbol_resolvers_adapter);
buffer_manager = ide_context_get_buffer_manager (priv->context);
@@ -2780,24 +2871,21 @@ ide_buffer_get_rename_provider (IdeBuffer *self)
}
/**
- * ide_buffer_get_symbol_resolver:
+ * ide_buffer_get_symbol_resolvers:
* @self: A #IdeBuffer.
*
- * Gets the symbol resolver for the buffer based on the current language.
+ * Gets the symbol resolvers for the buffer based on the current language.
*
- * Returns: (nullable) (transfer none): An #IdeSymbolResolver or %NULL.
+ * Returns: (nullable) (transfer none): An #IdeExtensionSetAdapter or %NULL.
*/
-IdeSymbolResolver *
-ide_buffer_get_symbol_resolver (IdeBuffer *self)
+IdeExtensionSetAdapter *
+ide_buffer_get_symbol_resolvers (IdeBuffer *self)
{
IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
g_return_val_if_fail (IDE_IS_BUFFER (self), NULL);
- if (priv->symbol_resolver_adapter != NULL)
- return ide_extension_adapter_get_extension (priv->symbol_resolver_adapter);
-
- return NULL;
+ return priv->symbol_resolvers_adapter;
}
/**
diff --git a/libide/buffers/ide-buffer.h b/libide/buffers/ide-buffer.h
index b229583..8ec313b 100644
--- a/libide/buffers/ide-buffer.h
+++ b/libide/buffers/ide-buffer.h
@@ -21,6 +21,7 @@
#include <gtksourceview/gtksource.h>
+#include "plugins/ide-extension-set-adapter.h"
#include "ide-types.h"
#include "formatting/ide-formatter-options.h"
@@ -62,65 +63,65 @@ struct _IdeBufferClass
gpointer _reserved8;
};
-void ide_buffer_format_selection_async (IdeBuffer *self,
- IdeFormatterOptions *options,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean ide_buffer_format_selection_finish (IdeBuffer *self,
- GAsyncResult *result,
- GError **error);
-gboolean ide_buffer_get_busy (IdeBuffer *self);
-gboolean ide_buffer_get_changed_on_volume (IdeBuffer *self);
-gsize ide_buffer_get_change_count (IdeBuffer *self);
-GBytes *ide_buffer_get_content (IdeBuffer *self);
-IdeContext *ide_buffer_get_context (IdeBuffer *self);
-IdeDiagnostic *ide_buffer_get_diagnostic_at_iter (IdeBuffer *self,
+void ide_buffer_format_selection_async (IdeBuffer *self,
+ IdeFormatterOptions *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_buffer_format_selection_finish (IdeBuffer *self,
+ GAsyncResult *result,
+ GError **error);
+gboolean ide_buffer_get_busy (IdeBuffer *self);
+gboolean ide_buffer_get_changed_on_volume (IdeBuffer *self);
+gsize ide_buffer_get_change_count (IdeBuffer *self);
+GBytes *ide_buffer_get_content (IdeBuffer *self);
+IdeContext *ide_buffer_get_context (IdeBuffer *self);
+IdeDiagnostic *ide_buffer_get_diagnostic_at_iter (IdeBuffer *self,
+ const GtkTextIter *iter);
+IdeFile *ide_buffer_get_file (IdeBuffer *self);
+IdeBufferLineFlags ide_buffer_get_line_flags (IdeBuffer *self,
+ guint line);
+gboolean ide_buffer_get_read_only (IdeBuffer *self);
+gboolean ide_buffer_get_spell_checking (IdeBuffer *self);
+gboolean ide_buffer_get_highlight_diagnostics (IdeBuffer *self);
+const gchar *ide_buffer_get_style_scheme_name (IdeBuffer *self);
+const gchar *ide_buffer_get_title (IdeBuffer *self);
+gchar *ide_buffer_get_uri (IdeBuffer *self);
+void ide_buffer_set_file (IdeBuffer *self,
+ IdeFile *file);
+void ide_buffer_set_highlight_diagnostics (IdeBuffer *self,
+ gboolean
highlight_diagnostics);
+void ide_buffer_set_spell_checking (IdeBuffer *self,
+ gboolean enable);
+void ide_buffer_set_style_scheme_name (IdeBuffer *self,
+ const gchar *style_scheme_name);
+void ide_buffer_trim_trailing_whitespace (IdeBuffer *self);
+void ide_buffer_check_for_volume_change (IdeBuffer *self);
+IdeSourceLocation *ide_buffer_get_insert_location (IdeBuffer *self);
+IdeSourceLocation *ide_buffer_get_iter_location (IdeBuffer *self,
+ const GtkTextIter *iter);
+void ide_buffer_get_iter_at_source_location (IdeBuffer *self,
+ GtkTextIter *iter,
+ IdeSourceLocation *location);
+void ide_buffer_rehighlight (IdeBuffer *self);
+void ide_buffer_get_selection_bounds (IdeBuffer *self,
+ GtkTextIter *insert,
+ GtkTextIter *selection);
+IdeRenameProvider *ide_buffer_get_rename_provider (IdeBuffer *self);
+IdeExtensionSetAdapter *ide_buffer_get_symbol_resolvers (IdeBuffer *self);
+void ide_buffer_get_symbol_at_location_async (IdeBuffer *self,
+ const GtkTextIter *location,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IdeSymbol *ide_buffer_get_symbol_at_location_finish (IdeBuffer *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_buffer_hold (IdeBuffer *self);
+void ide_buffer_release (IdeBuffer *self);
+gchar *ide_buffer_get_word_at_iter (IdeBuffer *self,
const GtkTextIter *iter);
-IdeFile *ide_buffer_get_file (IdeBuffer *self);
-IdeBufferLineFlags ide_buffer_get_line_flags (IdeBuffer *self,
- guint line);
-gboolean ide_buffer_get_read_only (IdeBuffer *self);
-gboolean ide_buffer_get_spell_checking (IdeBuffer *self);
-gboolean ide_buffer_get_highlight_diagnostics (IdeBuffer *self);
-const gchar *ide_buffer_get_style_scheme_name (IdeBuffer *self);
-const gchar *ide_buffer_get_title (IdeBuffer *self);
-gchar *ide_buffer_get_uri (IdeBuffer *self);
-void ide_buffer_set_file (IdeBuffer *self,
- IdeFile *file);
-void ide_buffer_set_highlight_diagnostics (IdeBuffer *self,
- gboolean highlight_diagnostics);
-void ide_buffer_set_spell_checking (IdeBuffer *self,
- gboolean enable);
-void ide_buffer_set_style_scheme_name (IdeBuffer *self,
- const gchar *style_scheme_name);
-void ide_buffer_trim_trailing_whitespace (IdeBuffer *self);
-void ide_buffer_check_for_volume_change (IdeBuffer *self);
-IdeSourceLocation *ide_buffer_get_insert_location (IdeBuffer *self);
-IdeSourceLocation *ide_buffer_get_iter_location (IdeBuffer *self,
- const GtkTextIter *iter);
-void ide_buffer_get_iter_at_source_location (IdeBuffer *self,
- GtkTextIter *iter,
- IdeSourceLocation *location);
-void ide_buffer_rehighlight (IdeBuffer *self);
-void ide_buffer_get_selection_bounds (IdeBuffer *self,
- GtkTextIter *insert,
- GtkTextIter *selection);
-IdeRenameProvider *ide_buffer_get_rename_provider (IdeBuffer *self);
-IdeSymbolResolver *ide_buffer_get_symbol_resolver (IdeBuffer *self);
-void ide_buffer_get_symbol_at_location_async (IdeBuffer *self,
- const GtkTextIter *location,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-IdeSymbol *ide_buffer_get_symbol_at_location_finish (IdeBuffer *self,
- GAsyncResult *result,
- GError **error);
-void ide_buffer_hold (IdeBuffer *self);
-void ide_buffer_release (IdeBuffer *self);
-gchar *ide_buffer_get_word_at_iter (IdeBuffer *self,
- const GtkTextIter *iter);
-void ide_buffer_sync_to_unsaved_files (IdeBuffer *self);
+void ide_buffer_sync_to_unsaved_files (IdeBuffer *self);
G_END_DECLS
diff --git a/libide/plugins/ide-extension-set-adapter.c b/libide/plugins/ide-extension-set-adapter.c
index 3490020..18b4192 100644
--- a/libide/plugins/ide-extension-set-adapter.c
+++ b/libide/plugins/ide-extension-set-adapter.c
@@ -43,6 +43,7 @@ struct _IdeExtensionSetAdapter
G_DEFINE_TYPE (IdeExtensionSetAdapter, ide_extension_set_adapter, IDE_TYPE_OBJECT)
enum {
+ EXTENSIONS_LOADED,
EXTENSION_ADDED,
EXTENSION_REMOVED,
LAST_SIGNAL
@@ -208,6 +209,7 @@ ide_extension_set_adapter_reload (IdeExtensionSetAdapter *self)
remove_extension (self, plugin_info, exten);
}
}
+ g_signal_emit (self, signals [EXTENSIONS_LOADED], 0);
}
static gboolean
@@ -443,6 +445,14 @@ ide_extension_set_adapter_class_init (IdeExtensionSetAdapterClass *klass)
2,
PEAS_TYPE_PLUGIN_INFO,
PEAS_TYPE_EXTENSION);
+
+ signals [EXTENSIONS_LOADED] =
+ g_signal_new ("extensions-loaded",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
static void
diff --git a/libide/sourceview/ide-source-view.c b/libide/sourceview/ide-source-view.c
index 1a1595e..ed181d1 100644
--- a/libide/sourceview/ide-source-view.c
+++ b/libide/sourceview/ide-source-view.c
@@ -200,6 +200,13 @@ typedef struct
GtkTextMark *word_end_mark;
} DefinitionHighlightData;
+typedef struct
+{
+ GPtrArray *resolvers;
+
+ IdeSourceLocation *location;
+} FindReferencesTaskData;
+
G_DEFINE_TYPE_WITH_PRIVATE (IdeSourceView, ide_source_view, GTK_SOURCE_TYPE_VIEW)
DZL_DEFINE_COUNTER (instances, "IdeSourceView", "Instances", "Number of IdeSourceView instances")
@@ -331,6 +338,25 @@ static void ide_source_view_maybe_overwrite (IdeSourceView *sel
const gchar *text,
gint len);
+static void
+find_references_task_data_free (FindReferencesTaskData *data)
+{
+ g_clear_pointer (&data->resolvers, g_ptr_array_unref);
+ g_clear_pointer (&data->location, ide_source_location_unref);
+ g_slice_free (FindReferencesTaskData, data);
+}
+
+static void
+find_references_task_get_extension (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ FindReferencesTaskData *data = user_data;
+
+ g_ptr_array_add (data->resolvers, IDE_SYMBOL_RESOLVER (extension));
+}
+
static SearchMovement *
search_movement_ref (SearchMovement *movement)
{
@@ -2770,6 +2796,10 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject *object,
kind = ide_symbol_get_kind (symbol);
srcloc = ide_symbol_get_definition_location (symbol);
+
+ if (srcloc == NULL)
+ srcloc = ide_symbol_get_declaration_location (symbol);
+
if (srcloc != NULL)
{
GtkTextIter word_start;
@@ -5096,6 +5126,9 @@ ide_source_view_goto_definition_symbol_cb (GObject *object,
srcloc = ide_symbol_get_definition_location (symbol);
+ if (srcloc == NULL)
+ srcloc = ide_symbol_get_declaration_location (symbol);
+
if (srcloc != NULL)
{
guint line = ide_source_location_get_line (srcloc);
@@ -5974,8 +6007,8 @@ ide_source_view_find_references_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- IdeSymbolResolver *resolver = (IdeSymbolResolver *)object;
- g_autoptr(IdeSourceView) self = user_data;
+ IdeSymbolResolver *symbol_resolver = (IdeSymbolResolver *)object;
+ IdeSourceView *self;
IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
g_autoptr(GPtrArray) references = NULL;
g_autoptr(GError) error = NULL;
@@ -5985,17 +6018,38 @@ ide_source_view_find_references_cb (GObject *object,
GtkTextMark *insert;
GtkTextIter iter;
GdkRectangle loc;
+ g_autoptr(GTask) task = user_data;
+ FindReferencesTaskData *data;
IDE_ENTRY;
- g_assert (IDE_IS_SYMBOL_RESOLVER (resolver));
+ g_assert (IDE_IS_SYMBOL_RESOLVER (symbol_resolver));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_SOURCE_VIEW (self));
- references = ide_symbol_resolver_find_references_finish (resolver, result, &error);
+ references = ide_symbol_resolver_find_references_finish (symbol_resolver, result, &error);
+
+ self = g_task_get_source_object (task);
+ data = g_task_get_task_data (task);
+
+ g_ptr_array_remove_index (data->resolvers, data->resolvers->len - 1);
+
+ /* If references are not found and symbol resolvers are left try those */
+ if (references == NULL && data->resolvers->len)
+ {
+ GCancellable *cancellable;
+ IdeSymbolResolver *resolver;
+
+ cancellable = g_task_get_cancellable (task);
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
- if (error != NULL)
- g_debug ("%s", error->message);
+ ide_symbol_resolver_find_references_async (resolver,
+ data->location,
+ cancellable,
+ ide_source_view_find_references_cb,
+ g_steal_pointer (&task));
+ return;
+ }
/* Ignore popover if we are no longer visible or not top-most */
if (!gtk_widget_get_visible (GTK_WIDGET (self)) ||
@@ -6107,28 +6161,45 @@ static void
ide_source_view_real_find_references (IdeSourceView *self)
{
IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
- g_autoptr(IdeSourceLocation) location = NULL;
+ g_autoptr(GTask) task = NULL;
+ IdeExtensionSetAdapter *adapter;
+ FindReferencesTaskData *data;
+ guint n_extensions;
IdeSymbolResolver *resolver;
IDE_ENTRY;
g_assert (IDE_IS_SOURCE_VIEW (self));
- resolver = ide_buffer_get_symbol_resolver (priv->buffer);
+ task = g_task_new (self, NULL, NULL, NULL);
+
+ adapter = ide_buffer_get_symbol_resolvers (priv->buffer);
+ n_extensions = ide_extension_set_adapter_get_n_extensions (adapter);
- if (resolver == NULL)
+ if (!n_extensions)
{
g_debug ("No symbol resolver is available");
+
IDE_EXIT;
}
- location = ide_buffer_get_insert_location (priv->buffer);
+ data = g_slice_new (FindReferencesTaskData);
+
+ data->resolvers = g_ptr_array_new_full (n_extensions, NULL);
+ data->location = ide_buffer_get_insert_location (priv->buffer);
+
+ g_task_set_task_data (task, data, (GDestroyNotify)find_references_task_data_free);
+
+ ide_extension_set_adapter_foreach (adapter, find_references_task_get_extension, data);
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+ /* Try each symbol resolver one by one to find references. */
ide_symbol_resolver_find_references_async (resolver,
- location,
+ data->location,
NULL,
ide_source_view_find_references_cb,
- g_object_ref (self));
+ g_steal_pointer (&task));
IDE_EXIT;
}
diff --git a/plugins/symbol-tree/gbp-symbol-layout-stack-addin.c
b/plugins/symbol-tree/gbp-symbol-layout-stack-addin.c
index 17df8ca..6ddef56 100644
--- a/plugins/symbol-tree/gbp-symbol-layout-stack-addin.c
+++ b/plugins/symbol-tree/gbp-symbol-layout-stack-addin.c
@@ -35,25 +35,75 @@ struct _GbpSymbolLayoutStackAddin {
guint cursor_moved_handler;
- guint resolver_loaded : 1;
+ guint resolvers_loaded : 1;
};
+typedef struct
+{
+ GPtrArray *resolvers;
+
+ IdeBuffer *buffer;
+ IdeSourceLocation *location;
+} SymbolResolverTaskData;
+
+static void
+symbol_resolver_task_data_free (SymbolResolverTaskData *data)
+{
+ g_clear_pointer (&data->resolvers, g_ptr_array_unref);
+ g_clear_object (&data->buffer);
+ g_clear_pointer (&data->location, ide_source_location_unref);
+ g_slice_free (SymbolResolverTaskData, data);
+}
+
+static void
+get_extension (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ SymbolResolverTaskData *data = user_data;
+
+ g_ptr_array_add (data->resolvers, IDE_SYMBOL_RESOLVER (extension));
+}
+
static void
gbp_symbol_layout_stack_addin_find_scope_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeSymbolResolver *symbol_resolver = (IdeSymbolResolver *)object;
- g_autoptr(GbpSymbolLayoutStackAddin) self = user_data;
+ GbpSymbolLayoutStackAddin *self;
g_autoptr(IdeSymbol) symbol = NULL;
g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = user_data;
+ SymbolResolverTaskData *data;
g_assert (IDE_IS_SYMBOL_RESOLVER (symbol_resolver));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (GBP_IS_SYMBOL_LAYOUT_STACK_ADDIN (self));
+ g_assert (G_IS_TASK (task));
symbol = ide_symbol_resolver_find_nearest_scope_finish (symbol_resolver, result, &error);
+ self = g_task_get_source_object (task);
+ data = g_task_get_task_data (task);
+
+ g_ptr_array_remove_index (data->resolvers, data->resolvers->len - 1);
+
+ /* If symbol is not found and symbol resolvers are left try those */
+ if (symbol == NULL && data->resolvers->len)
+ {
+ IdeSymbolResolver *resolver;
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+ ide_symbol_resolver_find_nearest_scope_async (resolver,
+ data->location,
+ self->scope_cancellable,
+ gbp_symbol_layout_stack_addin_find_scope_cb,
+ g_steal_pointer (&task));
+
+ return;
+ }
+
if (error != NULL &&
!(g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) ||
@@ -79,19 +129,35 @@ gbp_symbol_layout_stack_addin_cursor_moved_cb (gpointer user_data)
if (buffer != NULL)
{
- IdeSymbolResolver *symbol_resolver = ide_buffer_get_symbol_resolver (buffer);
+ IdeExtensionSetAdapter *adapter;
- if (symbol_resolver != NULL)
+ adapter = ide_buffer_get_symbol_resolvers (buffer);
+
+ if (ide_extension_set_adapter_get_n_extensions (adapter))
{
- g_autoptr(IdeSourceLocation) location = ide_buffer_get_insert_location (buffer);
+ g_autoptr(GTask) task = NULL;
+ SymbolResolverTaskData *data;
+ IdeSymbolResolver *resolver;
self->scope_cancellable = g_cancellable_new ();
- ide_symbol_resolver_find_nearest_scope_async (symbol_resolver,
- location,
+ task = g_task_new (self, self->scope_cancellable, NULL, NULL);
+
+ data = g_slice_new0 (SymbolResolverTaskData);
+ data->resolvers = g_ptr_array_new ();
+ data->location = ide_buffer_get_insert_location (buffer);
+
+ ide_extension_set_adapter_foreach (adapter, get_extension, data);
+
+ g_task_set_task_data (task, data, (GDestroyNotify)symbol_resolver_task_data_free);
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+ /* Go through symbol resolvers one by one to find nearest scope */
+ ide_symbol_resolver_find_nearest_scope_async (resolver,
+ data->location,
self->scope_cancellable,
gbp_symbol_layout_stack_addin_find_scope_cb,
- g_object_ref (self));
+ g_steal_pointer (&task));
}
}
@@ -135,34 +201,60 @@ gbp_symbol_layout_stack_addin_get_symbol_tree_cb (GObject *object,
gpointer user_data)
{
IdeSymbolResolver *symbol_resolver = (IdeSymbolResolver *)object;
- g_autoptr(GbpSymbolLayoutStackAddin) self = user_data;
+ GbpSymbolLayoutStackAddin *self;
g_autoptr(IdeSymbolTree) tree = NULL;
g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) task = user_data;
+ SymbolResolverTaskData *data;
+ g_assert (G_IS_TASK (task));
g_assert (IDE_IS_SYMBOL_RESOLVER (symbol_resolver));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (GBP_IS_SYMBOL_LAYOUT_STACK_ADDIN (self));
tree = ide_symbol_resolver_get_symbol_tree_finish (symbol_resolver, result, &error);
+ self = g_task_get_source_object (task);
+ data = g_task_get_task_data (task);
+
+ g_ptr_array_remove_index (data->resolvers, data->resolvers->len - 1);
+
+ /* If tree is not fetched and symbol resolvers are left then try those */
+ if (tree == NULL && data->resolvers->len)
+ {
+ GFile *file;
+ IdeSymbolResolver *resolver;
+
+ file = ide_file_get_file (ide_buffer_get_file (data->buffer));
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+
+ ide_symbol_resolver_get_symbol_tree_async (resolver,
+ file,
+ data->buffer,
+ self->cancellable,
+ gbp_symbol_layout_stack_addin_get_symbol_tree_cb,
+ g_steal_pointer (&task));
+ return;
+ }
+
if (error != NULL &&
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
- g_warning ("%s", error->message);
+ g_warning ("Failed to get symbol tree%s", error->message);
/* If we were destroyed, short-circuit */
- if (self->button == NULL)
- return;
-
- gbp_symbol_menu_button_set_symbol_tree (self->button, tree);
+ if (self->button != NULL)
+ gbp_symbol_menu_button_set_symbol_tree (self->button, tree);
}
static void
gbp_symbol_layout_stack_addin_update_tree (GbpSymbolLayoutStackAddin *self,
IdeBuffer *buffer)
{
- IdeSymbolResolver *symbol_resolver;
+ IdeExtensionSetAdapter *adapter;
IdeFile *file;
+ g_autoptr(GTask) task = NULL;
+ SymbolResolverTaskData *data;
+ IdeSymbolResolver *resolver;
g_assert (GBP_IS_SYMBOL_LAYOUT_STACK_ADDIN (self));
g_assert (IDE_IS_BUFFER (buffer));
@@ -171,12 +263,12 @@ gbp_symbol_layout_stack_addin_update_tree (GbpSymbolLayoutStackAddin *self,
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
- symbol_resolver = ide_buffer_get_symbol_resolver (buffer);
+ adapter = ide_buffer_get_symbol_resolvers (buffer);
- g_assert (!symbol_resolver || IDE_IS_SYMBOL_RESOLVER (symbol_resolver));
+ gtk_widget_set_visible (GTK_WIDGET (self->button),
+ ide_extension_set_adapter_get_n_extensions (adapter));
- gtk_widget_set_visible (GTK_WIDGET (self->button), symbol_resolver != NULL);
- if (symbol_resolver == NULL)
+ if (!ide_extension_set_adapter_get_n_extensions (adapter))
return;
file = ide_buffer_get_file (buffer);
@@ -184,12 +276,23 @@ gbp_symbol_layout_stack_addin_update_tree (GbpSymbolLayoutStackAddin *self,
self->cancellable = g_cancellable_new ();
- ide_symbol_resolver_get_symbol_tree_async (symbol_resolver,
+ task = g_task_new (self, self->cancellable, NULL, NULL);
+
+ data = g_slice_new0 (SymbolResolverTaskData);
+ data->resolvers = g_ptr_array_new ();
+ data->buffer = g_object_ref (buffer);
+
+ ide_extension_set_adapter_foreach (adapter, get_extension, data);
+
+ g_task_set_task_data (task, data, (GDestroyNotify)symbol_resolver_task_data_free);
+
+ resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
+ ide_symbol_resolver_get_symbol_tree_async (resolver,
ide_file_get_file (file),
- buffer,
+ data->buffer,
self->cancellable,
gbp_symbol_layout_stack_addin_get_symbol_tree_cb,
- g_object_ref (self));
+ g_steal_pointer (&task));
}
static void
@@ -227,7 +330,8 @@ gbp_symbol_layout_stack_addin_bind (GbpSymbolLayoutStackAddin *self,
IdeBuffer *buffer,
DzlSignalGroup *buffer_signals)
{
- IdeSymbolResolver *symbol_resolver;
+ IdeExtensionSetAdapter *adapter;
+ guint n_extensions;
g_assert (GBP_IS_SYMBOL_LAYOUT_STACK_ADDIN (self));
g_assert (IDE_IS_BUFFER (buffer));
@@ -237,13 +341,16 @@ gbp_symbol_layout_stack_addin_bind (GbpSymbolLayoutStackAddin *self,
gbp_symbol_menu_button_set_symbol (self->button, NULL);
- if (self->resolver_loaded)
+ if (self->resolvers_loaded)
return;
- if (NULL != (symbol_resolver = ide_buffer_get_symbol_resolver (buffer)))
- self->resolver_loaded = TRUE;
+ adapter = ide_buffer_get_symbol_resolvers (buffer);
+ n_extensions = ide_extension_set_adapter_get_n_extensions (adapter);
- gtk_widget_set_visible (GTK_WIDGET (self->button), symbol_resolver != NULL);
+ if (n_extensions)
+ self->resolvers_loaded = TRUE;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->button), n_extensions);
gbp_symbol_layout_stack_addin_update_tree (self, buffer);
}
@@ -263,24 +370,27 @@ gbp_symbol_layout_stack_addin_unbind (GbpSymbolLayoutStackAddin *self,
g_clear_object (&self->scope_cancellable);
gtk_widget_hide (GTK_WIDGET (self->button));
- self->resolver_loaded = FALSE;
+ self->resolvers_loaded = FALSE;
}
static void
-gbp_symbol_layout_stack_addin_symbol_resolver_loaded (GbpSymbolLayoutStackAddin *self,
- IdeBuffer *buffer)
+gbp_symbol_layout_stack_addin_symbol_resolvers_loaded (GbpSymbolLayoutStackAddin *self,
+ IdeBuffer *buffer)
{
- IdeSymbolResolver *symbol_resolver;
+ IdeExtensionSetAdapter *adapter;
+ guint n_extensions;
g_assert (GBP_IS_SYMBOL_LAYOUT_STACK_ADDIN (self));
g_assert (IDE_IS_BUFFER (buffer));
- if (self->resolver_loaded)
+ if (self->resolvers_loaded)
return;
- symbol_resolver = ide_buffer_get_symbol_resolver (buffer);
- gtk_widget_set_visible (GTK_WIDGET (self->button), symbol_resolver != NULL);
- self->resolver_loaded = TRUE;
+ adapter = ide_buffer_get_symbol_resolvers (buffer);
+ n_extensions = ide_extension_set_adapter_get_n_extensions (adapter);
+
+ gtk_widget_set_visible (GTK_WIDGET (self->button), n_extensions);
+ self->resolvers_loaded = TRUE;
gbp_symbol_layout_stack_addin_update_tree (self, buffer);
}
@@ -333,8 +443,8 @@ gbp_symbol_layout_stack_addin_load (IdeLayoutStackAddin *addin,
G_CALLBACK (gbp_symbol_layout_stack_addin_change_settled),
self);
dzl_signal_group_connect_swapped (self->buffer_signals,
- "symbol-resolver-loaded",
- G_CALLBACK (gbp_symbol_layout_stack_addin_symbol_resolver_loaded),
+ "symbol-resolvers-loaded",
+ G_CALLBACK (gbp_symbol_layout_stack_addin_symbol_resolvers_loaded),
self);
}
diff --git a/tests/meson.build b/tests/meson.build
index 9d555c7..a998e40 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -13,20 +13,28 @@ ide_test_cflags = [
'-DTEST_DATA_DIR="@0@/data/"'.format(meson.current_source_dir()),
]
+ide_test_deps = [
+ libide_dep,
+ libpeas_dep,
+]
+
ide_context = executable('test-ide-context',
'test-ide-context.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-context', ide_context,
env: ide_test_env,
)
-
ide_back_forward_list = executable('test-ide-back-forward-list',
'test-ide-back-forward-list.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-back-forward-list', ide_back_forward_list,
env: ide_test_env,
@@ -36,7 +44,9 @@ test('test-ide-back-forward-list', ide_back_forward_list,
ide_buffer_manager = executable('test-ide-buffer-manager',
'test-ide-buffer-manager.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-buffer-manager', ide_buffer_manager,
env: ide_test_env,
@@ -46,7 +56,9 @@ test('test-ide-buffer-manager', ide_buffer_manager,
ide_buffer = executable('test-ide-buffer',
'test-ide-buffer.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-buffer', ide_buffer,
env: ide_test_env,
@@ -56,7 +68,9 @@ test('test-ide-buffer', ide_buffer,
ide_doap = executable('test-ide-doap',
'test-ide-doap.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-doap', ide_doap,
env: ide_test_env,
@@ -66,7 +80,9 @@ test('test-ide-doap', ide_doap,
ide_file_settings = executable('test-ide-file-settings',
'test-ide-file-settings.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-file-settings', ide_file_settings,
env: ide_test_env,
@@ -77,8 +93,7 @@ ide_indenter = executable('test-ide-indenter',
'test-ide-indenter.c',
c_args: ide_test_cflags,
dependencies: [
- libide_dep,
- libpeas_dep,
+ ide_test_deps,
],
)
#test('test-ide-indenter', ide_indenter,
@@ -89,7 +104,9 @@ ide_indenter = executable('test-ide-indenter',
ide_vcs_uri = executable('test-ide-vcs-uri',
'test-ide-vcs-uri.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-vcs-uri', ide_vcs_uri,
env: ide_test_env,
@@ -99,7 +116,9 @@ test('test-ide-vcs-uri', ide_vcs_uri,
ide_uri = executable('test-ide-uri',
'test-ide-uri.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
test('test-ide-uri', ide_uri,
env: ide_test_env,
@@ -109,7 +128,9 @@ test('test-ide-uri', ide_uri,
test_vim = executable('test-vim',
'test-vim.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
#test('test-vim', test_vim,
# env: ide_test_env,
@@ -119,7 +140,9 @@ test_vim = executable('test-vim',
test_snippet_parser = executable('test-snippet-parser',
'test-snippet-parser.c',
c_args: ide_test_cflags,
- dependencies: libide_dep,
+ dependencies: [
+ ide_test_deps,
+ ],
)
#test('test-snippet-parser', test_snippet_parser,
# env: ide_test_env,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]