[gnome-builder/gnome-builder-3-18] ctags: delegate building tags to the build system when possible
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/gnome-builder-3-18] ctags: delegate building tags to the build system when possible
- Date: Tue, 13 Oct 2015 07:41:15 +0000 (UTC)
commit 4d387d20dffd58a0fd5d034e3eb575630fbf1bc6
Author: Christian Hergert <chergert redhat com>
Date: Mon Oct 12 12:39:31 2015 -0400
ctags: delegate building tags to the build system when possible
If the build system implements IdeTagsBuilder, we can defer our building
of tags to that instead of doing it ourself.
plugins/ctags/ide-ctags-builder.c | 71 +------------------
plugins/ctags/ide-ctags-builder.h | 3 +-
plugins/ctags/ide-ctags-index.c | 32 ++++++++-
plugins/ctags/ide-ctags-index.h | 4 +-
plugins/ctags/ide-ctags-service.c | 140 ++++++++++++++++++++++++++++++++++---
5 files changed, 169 insertions(+), 81 deletions(-)
---
diff --git a/plugins/ctags/ide-ctags-builder.c b/plugins/ctags/ide-ctags-builder.c
index 291e64a..0935655 100644
--- a/plugins/ctags/ide-ctags-builder.c
+++ b/plugins/ctags/ide-ctags-builder.c
@@ -234,12 +234,12 @@ ide_ctags_builder_build_worker (GTask *task,
g_object_ref (task));
}
-static void
-ide_ctags_builder_do_build (IdeCtagsBuilder *self)
+void
+ide_ctags_builder_rebuild (IdeCtagsBuilder *self)
{
g_autoptr(GTask) task = NULL;
- g_assert (IDE_IS_CTAGS_BUILDER (self));
+ g_return_if_fail (IDE_IS_CTAGS_BUILDER (self));
/* Make sure we aren't already in shutdown. */
if (!ide_object_hold (IDE_OBJECT (self)))
@@ -249,51 +249,6 @@ ide_ctags_builder_do_build (IdeCtagsBuilder *self)
ide_thread_pool_push_task (IDE_THREAD_POOL_INDEXER, task, ide_ctags_builder_build_worker);
}
-static gboolean
-ide_ctags_builder_build_timeout (gpointer data)
-{
- IdeCtagsBuilder *self = data;
-
- g_assert (IDE_IS_CTAGS_BUILDER (self));
-
- self->build_timeout = 0;
-
- if (self->is_building == FALSE)
- {
- self->is_building = TRUE;
- ide_ctags_builder_do_build (self);
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-ide_ctags_builder__buffer_saved_cb (IdeCtagsBuilder *self,
- IdeBuffer *buffer,
- IdeBufferManager *buffer_manager)
-{
- g_assert (IDE_IS_CTAGS_BUILDER (self));
- g_assert (IDE_IS_BUFFER (buffer));
- g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
-
- if (self->build_timeout != 0)
- {
- g_source_remove (self->build_timeout);
- self->build_timeout = 0;
- }
-
- /*
- * TODO: We will need to make ctags code insight check a few keys,
- * such as symbol resolving, autocompletion, highlight, etc.
- */
- if (!g_settings_get_boolean (self->settings, "ctags-autocompletion"))
- return;
-
- self->build_timeout = g_timeout_add_seconds (BUILD_CTAGS_DELAY_SECONDS,
- ide_ctags_builder_build_timeout,
- self);
-}
-
static void
ide_ctags_builder__ctags_path_changed (IdeCtagsBuilder *self,
const gchar *key,
@@ -310,25 +265,6 @@ ide_ctags_builder__ctags_path_changed (IdeCtagsBuilder *self,
}
static void
-ide_ctags_builder_constructed (GObject *object)
-{
- IdeCtagsBuilder *self = (IdeCtagsBuilder *)object;
- IdeBufferManager *buffer_manager;
- IdeContext *context;
-
- context = ide_object_get_context (IDE_OBJECT (self));
- buffer_manager = ide_context_get_buffer_manager (context);
-
- g_signal_connect_object (buffer_manager,
- "buffer-saved",
- G_CALLBACK (ide_ctags_builder__buffer_saved_cb),
- self,
- G_CONNECT_SWAPPED);
-
- G_OBJECT_CLASS (ide_ctags_builder_parent_class)->constructed (object);
-}
-
-static void
ide_ctags_builder_finalize (GObject *object)
{
IdeCtagsBuilder *self = (IdeCtagsBuilder *)object;
@@ -351,7 +287,6 @@ ide_ctags_builder_class_init (IdeCtagsBuilderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->constructed = ide_ctags_builder_constructed;
object_class->finalize = ide_ctags_builder_finalize;
gSignals [TAGS_BUILT] =
diff --git a/plugins/ctags/ide-ctags-builder.h b/plugins/ctags/ide-ctags-builder.h
index fe25e2a..c07ba89 100644
--- a/plugins/ctags/ide-ctags-builder.h
+++ b/plugins/ctags/ide-ctags-builder.h
@@ -27,7 +27,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeCtagsBuilder, ide_ctags_builder, IDE, CTAGS_BUILDER, IdeObject)
-IdeCtagsBuilder *ide_ctags_builder_new (void);
+IdeCtagsBuilder *ide_ctags_builder_new (void);
+void ide_ctags_builder_rebuild (IdeCtagsBuilder *self);
G_END_DECLS
diff --git a/plugins/ctags/ide-ctags-index.c b/plugins/ctags/ide-ctags-index.c
index f512717..2adfdb6 100644
--- a/plugins/ctags/ide-ctags-index.c
+++ b/plugins/ctags/ide-ctags-index.c
@@ -36,11 +36,14 @@ struct _IdeCtagsIndex
GBytes *buffer;
GFile *file;
gchar *path_root;
+
+ guint64 mtime;
};
enum {
PROP_0,
PROP_FILE,
+ PROP_MTIME,
PROP_PATH_ROOT,
LAST_PROP
};
@@ -311,6 +314,10 @@ ide_ctags_index_get_property (GObject *object,
g_value_set_object (value, ide_ctags_index_get_file (self));
break;
+ case PROP_MTIME:
+ g_value_set_uint64 (value, self->mtime);
+ break;
+
case PROP_PATH_ROOT:
g_value_set_string (value, ide_ctags_index_get_path_root (self));
break;
@@ -334,6 +341,10 @@ ide_ctags_index_set_property (GObject *object,
ide_ctags_index_set_file (self, g_value_get_object (value));
break;
+ case PROP_MTIME:
+ self->mtime = g_value_get_uint64 (value);
+ break;
+
case PROP_PATH_ROOT:
ide_ctags_index_set_path_root (self, g_value_get_string (value));
break;
@@ -382,6 +393,15 @@ ide_ctags_index_class_init (IdeCtagsIndexClass *klass)
G_TYPE_FILE,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |G_PARAM_STATIC_STRINGS));
+ gParamSpecs [PROP_MTIME] =
+ g_param_spec_uint64 ("mtime",
+ "Mtime",
+ "Mtime",
+ 0,
+ G_MAXUINT64,
+ 0,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gParamSpecs [PROP_PATH_ROOT] =
g_param_spec_string ("path-root",
"Path Root",
@@ -454,7 +474,8 @@ async_initable_iface_init (GAsyncInitableIface *iface)
IdeCtagsIndex *
ide_ctags_index_new (GFile *file,
- const gchar *path_root)
+ const gchar *path_root,
+ guint64 mtime)
{
g_autoptr(GFile) parent = NULL;
g_autofree gchar *real_path_root = NULL;
@@ -470,6 +491,7 @@ ide_ctags_index_new (GFile *file,
return g_object_new (IDE_TYPE_CTAGS_INDEX,
"file", file,
"path-root", path_root,
+ "mtime", mtime,
NULL);
}
@@ -610,3 +632,11 @@ _ide_ctags_index_register_type (GTypeModule *module)
{
ide_ctags_index_register_type (module);
}
+
+guint64
+ide_ctags_index_get_mtime (IdeCtagsIndex *self)
+{
+ g_return_val_if_fail (IDE_IS_CTAGS_INDEX (self), 0);
+
+ return self->mtime;
+}
diff --git a/plugins/ctags/ide-ctags-index.h b/plugins/ctags/ide-ctags-index.h
index ddbcfde..c7848b3 100644
--- a/plugins/ctags/ide-ctags-index.h
+++ b/plugins/ctags/ide-ctags-index.h
@@ -56,7 +56,8 @@ typedef struct
} IdeCtagsIndexEntry;
IdeCtagsIndex *ide_ctags_index_new (GFile *file,
- const gchar *path_root);
+ const gchar *path_root,
+ guint64 mtime);
void ide_ctags_index_load_async (IdeCtagsIndex *self,
GFile *file,
GCancellable *cancellable,
@@ -76,6 +77,7 @@ const IdeCtagsIndexEntry *ide_ctags_index_lookup (IdeCtagsIndex *s
const IdeCtagsIndexEntry *ide_ctags_index_lookup_prefix (IdeCtagsIndex *self,
const gchar *keyword,
gsize *length);
+guint64 ide_ctags_index_get_mtime (IdeCtagsIndex *self);
gint ide_ctags_index_entry_compare (gconstpointer a,
gconstpointer b);
diff --git a/plugins/ctags/ide-ctags-service.c b/plugins/ctags/ide-ctags-service.c
index bd317c0..0aaa1de 100644
--- a/plugins/ctags/ide-ctags-service.c
+++ b/plugins/ctags/ide-ctags-service.c
@@ -23,28 +23,30 @@
#include "egg-task-cache.h"
+#include "ide-buffer-manager.h"
#include "ide-context.h"
#include "ide-ctags-builder.h"
#include "ide-ctags-completion-provider.h"
-#include "ide-ctags-service.h"
+#include "ide-ctags-highlighter.h"
#include "ide-ctags-index.h"
+#include "ide-ctags-service.h"
#include "ide-debug.h"
#include "ide-global.h"
#include "ide-project.h"
+#include "ide-tags-builder.h"
#include "ide-vcs.h"
-#include "ide-ctags-highlighter.h"
struct _IdeCtagsService
{
- IdeObject parent_instance;
+ IdeObject parent_instance;
- EggTaskCache *indexes;
- GCancellable *cancellable;
- IdeCtagsBuilder *builder;
- GPtrArray *highlighters;
- GPtrArray *completions;
+ EggTaskCache *indexes;
+ GCancellable *cancellable;
+ IdeCtagsBuilder *builder;
+ GPtrArray *highlighters;
+ GPtrArray *completions;
- guint miner_ran : 1;
+ guint build_tags_timeout;
};
static void service_iface_init (IdeServiceInterface *iface);
@@ -70,6 +72,18 @@ ide_ctags_service_build_index_init_cb (GObject *object,
g_task_return_pointer (task, g_object_ref (index), g_object_unref);
}
+static guint64
+get_file_mtime (GFile *file)
+{
+ g_autoptr(GFileInfo) info = NULL;
+
+ if ((info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL)))
+ return g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ return 0;
+}
+
static gchar *
resolve_path_root (IdeCtagsService *self,
GFile *file)
@@ -128,7 +142,7 @@ ide_ctags_service_build_index_cb (EggTaskCache *cache,
g_assert (G_IS_TASK (task));
path_root = resolve_path_root (self, file);
- index = ide_ctags_index_new (file, path_root);
+ index = ide_ctags_index_new (file, path_root, get_file_mtime (file));
uri = g_file_get_uri (file);
g_debug ("Building ctags in memory index for %s", uri);
@@ -183,12 +197,29 @@ ide_ctags_service_tags_loaded_cb (GObject *object,
}
static gboolean
+file_is_newer (IdeCtagsIndex *index,
+ GFile *file)
+{
+ g_assert (IDE_IS_CTAGS_INDEX (index));
+ g_assert (G_IS_FILE (file));
+
+ return get_file_mtime (file) > ide_ctags_index_get_mtime (index);
+}
+
+static gboolean
do_load (gpointer data)
{
struct {
IdeCtagsService *self;
GFile *file;
} *pair = data;
+ IdeCtagsIndex *prev;
+
+ if ((prev = egg_task_cache_peek (pair->self->indexes, pair->file)))
+ {
+ if (!file_is_newer (prev, pair->file))
+ goto cleanup;
+ }
egg_task_cache_get_async (pair->self->indexes,
pair->file,
@@ -197,6 +228,7 @@ do_load (gpointer data)
ide_ctags_service_tags_loaded_cb,
g_object_ref (pair->self));
+cleanup:
g_object_unref (pair->self);
g_object_unref (pair->file);
g_slice_free1 (sizeof *pair, pair);
@@ -364,13 +396,99 @@ ide_ctags_service_tags_built_cb (IdeCtagsService *self,
}
static void
+build_system_tags_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeTagsBuilder *builder = (IdeTagsBuilder *)object;
+ g_autoptr(IdeCtagsService) self = user_data;
+
+ g_assert (IDE_IS_TAGS_BUILDER (builder));
+
+ ide_ctags_service_mine (self);
+}
+
+static gboolean
+restart_miner (gpointer data)
+{
+ IdeCtagsService *self = data;
+ IdeContext *context;
+
+ g_assert (IDE_IS_CTAGS_SERVICE (self));
+
+ self->build_tags_timeout = 0;
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+
+ if (context != NULL)
+ {
+ IdeBuildSystem *build_system;
+
+ build_system = ide_context_get_build_system (context);
+
+ if (IDE_IS_TAGS_BUILDER (build_system))
+ {
+ IdeVcs *vcs;
+ GFile *workdir;
+
+ vcs = ide_context_get_vcs (context);
+ workdir = ide_vcs_get_working_directory (vcs);
+ ide_tags_builder_build_async (IDE_TAGS_BUILDER (build_system), workdir, TRUE, NULL,
+ build_system_tags_cb, g_object_ref (self));;
+ goto finish;
+ }
+ }
+
+ ide_ctags_builder_rebuild (self->builder);
+
+finish:
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+ide_ctags_service_buffer_saved (IdeCtagsService *self,
+ IdeBuffer *buffer,
+ IdeBufferManager *buffer_manager)
+{
+ g_assert (IDE_IS_CTAGS_SERVICE (self));
+ g_assert (IDE_IS_BUFFER (buffer));
+ g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+
+ if (self->build_tags_timeout == 0)
+ self->build_tags_timeout = g_timeout_add_seconds (5, restart_miner, self);
+}
+
+static void
ide_ctags_service_context_loaded (IdeService *service)
{
IdeCtagsService *self = (IdeCtagsService *)service;
+ IdeContext *context;
+ IdeBuildSystem *build_system;
+
+ IDE_ENTRY;
g_assert (IDE_IS_CTAGS_SERVICE (self));
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_context_get_build_system (context);
+
+ if (IDE_IS_TAGS_BUILDER (build_system))
+ {
+ IdeBufferManager *buffer_manager;
+
+ buffer_manager = ide_context_get_buffer_manager (context);
+
+ g_signal_connect_object (buffer_manager,
+ "buffer-saved",
+ G_CALLBACK (ide_ctags_service_buffer_saved),
+ self,
+ G_CONNECT_SWAPPED);
+ }
+
ide_ctags_service_mine (self);
+
+ IDE_EXIT;
}
static void
@@ -402,6 +520,7 @@ ide_ctags_service_stop (IdeService *service)
if (self->cancellable && !g_cancellable_is_cancelled (self->cancellable))
g_cancellable_cancel (self->cancellable);
+ ide_clear_source (&self->build_tags_timeout);
g_clear_object (&self->cancellable);
g_clear_object (&self->builder);
}
@@ -413,6 +532,7 @@ ide_ctags_service_finalize (GObject *object)
IDE_ENTRY;
+ ide_clear_source (&self->build_tags_timeout);
g_clear_object (&self->indexes);
g_clear_object (&self->cancellable);
g_clear_pointer (&self->highlighters, g_ptr_array_unref);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]