[gnome-builder] code-index: Adding IdeCodeIndexBuilder
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] code-index: Adding IdeCodeIndexBuilder
- Date: Fri, 1 Sep 2017 22:24:50 +0000 (UTC)
commit 4e779090eb1d3aab63309b50d898d30798836e45
Author: Anoop Chandu <anoopchandu96 gmail com>
Date: Tue Aug 29 21:10:16 2017 +0530
code-index: Adding IdeCodeIndexBuilder
This class will index a directory recursively and store that into
disk asynchronously. After Indexing it will load indexes using
IdeCodeIndexIndex.
https://bugzilla.gnome.org/show_bug.cgi?id=786700
plugins/code-index/ide-code-index-builder.c | 858 +++++++++++++++++++++++++++
plugins/code-index/ide-code-index-builder.h | 48 ++
2 files changed, 906 insertions(+), 0 deletions(-)
---
diff --git a/plugins/code-index/ide-code-index-builder.c b/plugins/code-index/ide-code-index-builder.c
new file mode 100644
index 0000000..2e80499
--- /dev/null
+++ b/plugins/code-index/ide-code-index-builder.c
@@ -0,0 +1,858 @@
+/* ide-code-index-builder.c
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail 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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-code-index-builder"
+
+#include <dazzle.h>
+#include <glib/gprintf.h>
+
+#include "ide-code-index-builder.h"
+#include "ide-persistent-map-builder.h"
+
+struct _IdeCodeIndexBuilder
+{
+ IdeObject parent;
+
+ IdeCodeIndexIndex *index;
+ IdeCodeIndexService *service;
+
+ GMutex indexed;
+
+ GHashTable *build_flags;
+};
+
+typedef struct
+{
+ GFile *directory;
+ GPtrArray *changes;
+ guint recursive : 1;
+} GetChangesTaskData;
+
+typedef struct
+{
+ GPtrArray *files;
+ GFile *destination;
+} IndexingData;
+
+G_DEFINE_TYPE (IdeCodeIndexBuilder, ide_code_index_builder, IDE_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_INDEX,
+ PROP_SERVICE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+get_changes_task_data_free (GetChangesTaskData *data)
+{
+ g_clear_object (&data->directory);
+ g_clear_pointer (&data->changes, g_ptr_array_unref);
+ g_slice_free (GetChangesTaskData, data);
+}
+
+static void
+indexing_data_free (IndexingData *data)
+{
+ if (data == NULL)
+ return;
+ g_clear_pointer (&data->files, g_ptr_array_unref);
+ g_clear_object (&data->destination);
+ g_slice_free (IndexingData, data);
+}
+
+static gboolean
+timeval_compare (GTimeVal a,
+ GTimeVal b)
+{
+ return ((a.tv_sec > b.tv_sec) || ((a.tv_sec == b.tv_sec) && (a.tv_usec > b.tv_usec)));
+}
+
+static gchar **
+ide_code_index_builder_get_build_flags (IdeCodeIndexBuilder *self,
+ GFile *file)
+{
+ g_autoptr(IdeFile) ide_file = NULL;
+
+ ide_file = ide_file_new (ide_object_get_context (IDE_OBJECT (self)), file);
+
+ return g_hash_table_lookup (self->build_flags, ide_file);
+}
+
+static GPtrArray *
+ide_code_index_builder_get_all_files (IdeCodeIndexBuilder *self,
+ GPtrArray *changes)
+{
+ g_autoptr(GPtrArray) all_files = NULL;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (changes != NULL);
+
+ all_files = g_ptr_array_new_with_free_func (g_object_unref);
+
+ for (guint i = 0; i < changes->len ; i++)
+ {
+ GPtrArray *dir_files;
+
+ dir_files = ((IndexingData *)g_ptr_array_index (changes, i))->files;
+
+ for (guint j = 0; j < dir_files->len; j++)
+ {
+ g_autoptr(IdeFile) file = NULL;
+
+ file = ide_file_new (ide_object_get_context (IDE_OBJECT(self)),
+ g_ptr_array_index (dir_files, j));
+
+ if (g_hash_table_lookup (self->build_flags, file) == NULL)
+ g_ptr_array_add (all_files, g_steal_pointer (&file));
+ }
+ }
+
+ return g_steal_pointer (&all_files);
+}
+
+/* Index directories: index all directores, store index and load index */
+
+static void
+ide_code_index_builder_index_file (IdeCodeIndexBuilder *self,
+ GFile *file,
+ guint32 file_id,
+ IdePersistentMapBuilder *map_builder,
+ DzlFuzzyIndexBuilder *fuzzy_builder,
+ GTask *task)
+{
+ g_autofree gchar *file_name = NULL;
+ g_autoptr(IdeCodeIndexEntries) entries = NULL;
+ g_autoptr(GError) error = NULL;
+ IdeCodeIndexer *indexer;
+ GCancellable *cancellable;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_FILE (file));
+ g_assert (IDE_IS_PERSISTENT_MAP_BUILDER (map_builder));
+ g_assert (DZL_IS_FUZZY_INDEX_BUILDER (fuzzy_builder));
+ g_assert (G_IS_TASK (task));
+
+ file_name = g_file_get_path (file);
+
+ if (NULL == (indexer = ide_code_index_service_get_code_indexer (self->service, file_name)))
+ return;
+
+ cancellable = g_task_get_cancellable (task);
+
+ if (NULL != (entries = ide_code_indexer_index_file (indexer,
+ file,
+ ide_code_index_builder_get_build_flags (self, file),
+ cancellable,
+ &error)))
+ {
+ gchar num[100];
+ IdeCodeIndexEntry *index_entry;
+
+ g_snprintf (num, sizeof (num), "%u", file_id);
+
+ /*
+ * Storing file_name:id and id:file_name into index, file_name:id will be
+ * used to check whether a file is there in index or not.
+ */
+ dzl_fuzzy_index_builder_set_metadata_uint32 (fuzzy_builder, file_name, file_id);
+ dzl_fuzzy_index_builder_set_metadata_string (fuzzy_builder, num, file_name);
+
+ while (NULL != (index_entry = ide_code_index_entries_get_next_entry (entries)))
+ {
+ g_autoptr(IdeCodeIndexEntry) entry = index_entry;
+ gchar *key;
+ gchar *name;
+ IdeSymbolKind kind;
+ IdeSymbolFlags flags;
+ guint begin_line;
+ guint begin_line_offset;
+
+ key = ide_code_index_entry_get_key (entry);
+ name = ide_code_index_entry_get_name (entry);
+ kind = ide_code_index_entry_get_kind (entry);
+ flags = ide_code_index_entry_get_flags (entry);
+
+ ide_code_index_entry_get_range (entry,
+ &begin_line,
+ &begin_line_offset,
+ NULL,
+ NULL);
+
+ /* In our index lines and offsets are 1-based */
+ if (key != NULL)
+ ide_persistent_map_builder_insert (map_builder,
+ key,
+ g_variant_new ("(uuuu)",
+ file_id,
+ begin_line, begin_line_offset,
+ flags),
+ flags & IDE_SYMBOL_FLAGS_IS_DEFINITION);
+ if (name != NULL)
+ dzl_fuzzy_index_builder_insert (fuzzy_builder,
+ name,
+ g_variant_new ("(uuuuu)",
+ file_id,
+ begin_line, begin_line_offset,
+ flags, kind),
+ 0);
+ }
+ }
+ else if (error != NULL)
+ {
+ g_message ("Failed to index file, %s", error->message);
+ }
+}
+
+static void
+ide_code_index_builder_index_directory (GTask *task,
+ gpointer source_object,
+ gpointer task_data_ptr,
+ GCancellable *cancellable)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)source_object;
+ IndexingData *data = task_data_ptr;
+ g_autoptr(GFile) keys_file = NULL;
+ g_autoptr(GFile) names_file = NULL;
+ g_autoptr(IdePersistentMapBuilder) map_builder = NULL;
+ g_autoptr(DzlFuzzyIndexBuilder) fuzzy_builder = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (data != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ map_builder = ide_persistent_map_builder_new ();
+ fuzzy_builder = dzl_fuzzy_index_builder_new ();
+
+ g_file_make_directory_with_parents (data->destination, NULL, NULL);
+
+ g_debug ("Indexing directory");
+
+ for (guint i = 0; i < data->files->len; i++)
+ {
+ if (g_task_return_error_if_cancelled (task))
+ return;
+
+ ide_code_index_builder_index_file (self,
+ g_ptr_array_index (data->files, i),
+ i + 1,
+ map_builder,
+ fuzzy_builder,
+ task);
+ }
+
+ g_debug ("Writing directory index");
+
+ keys_file = g_file_get_child (data->destination, "SymbolKeys");
+
+ if (!ide_persistent_map_builder_write (map_builder,
+ keys_file,
+ G_PRIORITY_LOW,
+ cancellable,
+ &error))
+ {
+ g_message ("Unable to write keys map, %s", error->message);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ dzl_fuzzy_index_builder_set_metadata_uint32 (fuzzy_builder,
+ "n_files",
+ data->files->len);
+
+ names_file = g_file_get_child (data->destination, "SymbolNames");
+
+ if (!dzl_fuzzy_index_builder_write (fuzzy_builder,
+ names_file,
+ G_PRIORITY_LOW,
+ cancellable,
+ &error))
+ {
+ g_message ("Unable to write fuzzy index, %s", error->message);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ if (!ide_code_index_index_load (self->index, data->destination, cancellable, &error))
+ {
+ g_message ("Unable to load indexes, %s", error->message);
+ g_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+ide_code_index_builder_index_directory_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+ g_autoptr(GTask) task = user_data;
+ guint n_threads;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_TASK (task));
+
+ g_mutex_lock (&self->indexed);
+
+ n_threads = GPOINTER_TO_UINT (g_task_get_task_data (task)) - 1;
+
+ if (n_threads)
+ g_task_set_task_data (task, GUINT_TO_POINTER (n_threads), NULL);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_mutex_unlock (&self->indexed);
+}
+
+static void
+ide_code_index_builder_index_directories_async (IdeCodeIndexBuilder *self,
+ GPtrArray *changes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) dirs_task = NULL;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (changes != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ dirs_task = g_task_new (self, cancellable, callback, user_data);
+
+ g_task_set_priority (dirs_task, G_PRIORITY_LOW);
+ g_task_set_task_data (dirs_task, GUINT_TO_POINTER (changes->len), NULL);
+
+ for (guint i = 0; i < changes->len; i++)
+ {
+ g_autoptr(GTask) dir_task = NULL;
+ IndexingData *idata;
+
+ dir_task = g_task_new (self,
+ cancellable,
+ ide_code_index_builder_index_directory_cb,
+ g_object_ref (dirs_task));
+
+ idata = g_ptr_array_index (changes, i);
+ g_ptr_array_index (changes, i) = NULL;
+
+ g_task_set_priority (dir_task, G_PRIORITY_LOW);
+ g_task_set_source_tag (dir_task, ide_code_index_builder_index_directories_async);
+ g_task_set_task_data (dir_task, idata, (GDestroyNotify)indexing_data_free);
+
+ ide_thread_pool_push_task (IDE_THREAD_POOL_INDEXER,
+ dir_task,
+ ide_code_index_builder_index_directory);
+ }
+}
+
+static gboolean
+ide_code_index_builder_index_directories_finish (IdeCodeIndexBuilder *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_assert (G_IS_TASK (task));
+
+ return g_task_propagate_boolean (task, error);
+}
+
+/* Get Changes: get all directories which are newer than index */
+
+static void
+ide_code_index_builder_get_changes (IdeCodeIndexBuilder *self,
+ GFile *directory,
+ GFile *destination,
+ gboolean recursive,
+ GPtrArray *changes,
+ GCancellable *cancellable)
+{
+ g_autoptr(GPtrArray) files = NULL;
+ g_autoptr(GPtrArray) directories = NULL;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GError) error = NULL;
+ gpointer infoptr;
+ GTimeVal max_mod_time = { 0 };
+ IdeVcs *vcs;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_FILE (directory));
+ g_assert (G_IS_FILE (destination));
+
+ vcs = ide_context_get_vcs (ide_object_get_context (IDE_OBJECT (self)));
+
+ if (ide_vcs_is_ignored (vcs, directory, NULL))
+ return;
+
+ if (NULL == (enumerator = g_file_enumerate_children (directory,
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ &error)))
+ {
+ g_message ("Failed to get children, %s", error->message);
+ return;
+ }
+
+ files = g_ptr_array_new_with_free_func (g_object_unref);
+ directories = g_ptr_array_new_with_free_func (g_free);
+
+ while (NULL != (infoptr = g_file_enumerator_next_file (enumerator, cancellable, NULL)))
+ {
+ g_autoptr(GFileInfo) info = infoptr;
+ const gchar *file_name;
+ GFileType type;
+
+ file_name = g_file_info_get_name (info);
+ type = g_file_info_get_file_type (info);
+
+ if (type == G_FILE_TYPE_DIRECTORY && recursive)
+ {
+ g_ptr_array_add (directories, g_strdup (file_name));
+ }
+ else if (type == G_FILE_TYPE_REGULAR)
+ {
+ if (NULL != ide_code_index_service_get_code_indexer (self->service, file_name))
+ {
+ GTimeVal mod_time;
+ g_autoptr(GFile) file = NULL;
+
+ g_file_info_get_modification_time (info, &mod_time);
+
+ if (timeval_compare (mod_time, max_mod_time))
+ max_mod_time = mod_time;
+
+ file = g_file_get_child (directory, file_name);
+
+ if (!ide_vcs_is_ignored (vcs, file, NULL))
+ g_ptr_array_add (files, g_steal_pointer (&file));
+ }
+ }
+ }
+
+ g_file_enumerator_close (enumerator, cancellable, NULL);
+
+ if ((files->len != 0) &&
+ !ide_code_index_index_load_if_nmod (self->index,
+ destination,
+ files,
+ max_mod_time,
+ cancellable,
+ NULL))
+ {
+ IndexingData *idata;
+
+ idata = g_slice_new0 (IndexingData);
+ idata->files = g_ptr_array_ref (files);
+ idata->destination = g_object_ref (destination);
+ g_ptr_array_add (changes, idata);
+ }
+
+ for (guint i = 0; i < directories->len; i++)
+ {
+ const gchar *file_name;
+ g_autoptr(GFile) sub_dir = NULL;
+ g_autoptr(GFile) sub_dest = NULL;
+
+ file_name = g_ptr_array_index (directories, i);
+ sub_dir = g_file_get_child (directory, file_name);
+ sub_dest = g_file_get_child (destination, file_name);
+
+ ide_code_index_builder_get_changes (self,
+ sub_dir,
+ sub_dest,
+ recursive,
+ changes,
+ cancellable);
+ }
+}
+
+static void
+ide_code_index_builder_get_changes_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data_ptr,
+ GCancellable *cancellable)
+{
+ IdeCodeIndexBuilder *self = source_object;
+ IdeContext *context;
+ const gchar *project_id;
+ GFile *workdir;
+ g_autoptr(GFile) destination = NULL;
+ g_autofree gchar *relative_path = NULL;
+ g_autofree gchar *destination_path = NULL;
+ GetChangesTaskData *data = task_data_ptr;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_TASK (task));
+ g_assert (data != NULL);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ project_id = ide_project_get_id (ide_context_get_project (context));
+ workdir = ide_vcs_get_working_directory (ide_context_get_vcs (context));
+ relative_path = g_file_get_relative_path (workdir, data->directory);
+ destination_path = g_build_filename (g_get_user_cache_dir (),
+ ide_get_program_name (),
+ "code-index",
+ project_id,
+ relative_path,
+ NULL);
+ destination = g_file_new_for_path (destination_path);
+
+ data->changes = g_ptr_array_new_with_free_func ((GDestroyNotify)indexing_data_free);
+
+ if (g_task_return_error_if_cancelled (task))
+ return;
+
+ ide_code_index_builder_get_changes (self,
+ data->directory,
+ destination,
+ data->recursive,
+ data->changes,
+ cancellable);
+
+ g_task_return_pointer (task, g_ptr_array_ref (data->changes), (GDestroyNotify)g_ptr_array_unref);
+}
+
+static void
+ide_code_index_builder_get_changes_async (IdeCodeIndexBuilder *self,
+ GFile *directory,
+ gboolean recursive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ GetChangesTaskData *data;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_FILE (directory));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ g_debug ("Getting file changes");
+
+ data = g_slice_new0 (GetChangesTaskData);
+
+ data->directory = g_object_ref (directory);
+ data->recursive = recursive;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ g_task_set_task_data (task, data, (GDestroyNotify)get_changes_task_data_free);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_source_tag (task, ide_code_index_builder_get_changes_async);
+
+ ide_thread_pool_push_task (IDE_THREAD_POOL_INDEXER,
+ task,
+ ide_code_index_builder_get_changes_worker);
+}
+
+static GPtrArray *
+ide_code_index_builder_get_changes_finish (IdeCodeIndexBuilder *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_assert (G_IS_TASK (task));
+
+ return g_task_propagate_pointer (task, error);
+}
+
+ /* Main task: get changes, retrive build flags and index directories */
+
+static void
+ide_code_index_builder_build_cb3 (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+ g_autoptr(GTask) main_task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_TASK (main_task));
+
+ if (ide_code_index_builder_index_directories_finish (self, result, &error))
+ g_task_return_boolean (main_task, TRUE);
+ else
+ g_task_return_error (main_task, error);
+}
+
+static void
+ide_code_index_builder_build_cb2 (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeCodeIndexBuilder *self;
+ IdeBuildSystem *build_system = (IdeBuildSystem *)object;
+ g_autoptr(GHashTable) build_flags = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GTask) main_task = user_data;
+ GPtrArray *changes = NULL;
+ GHashTableIter iter;
+ gpointer key = NULL;
+ gpointer value = NULL;
+ GCancellable *cancellable;
+
+ g_assert (IDE_IS_BUILD_SYSTEM (build_system));
+ g_assert (G_IS_TASK (main_task));
+
+ if (NULL == (build_flags = ide_build_system_get_build_flags_for_files_finish (build_system,
+ result,
+ &error)))
+ {
+ g_message ("Failed to fetch build flags %s", error->message);
+ g_task_return_error (main_task, g_steal_pointer (&error));
+ return;
+ }
+ else if (g_task_return_error_if_cancelled (main_task))
+ {
+ return;
+ }
+
+ self = g_task_get_source_object (main_task);
+ cancellable = g_task_get_cancellable (main_task);
+ changes = g_task_get_task_data (main_task);
+
+ /* Update self->build_flags hash table with new flags */
+ g_hash_table_iter_init (&iter, build_flags);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ g_hash_table_iter_steal (&iter);
+ g_hash_table_insert (self->build_flags, key, value);
+ }
+
+ ide_code_index_builder_index_directories_async (self,
+ changes,
+ cancellable,
+ ide_code_index_builder_build_cb3,
+ g_steal_pointer (&main_task));
+}
+
+static void
+ide_code_index_builder_build_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+ g_autoptr(GTask) main_task = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) changes = NULL;
+ IdeBuildSystem *build_system;
+ IdeContext *context;
+ g_autoptr(GPtrArray) files = NULL;
+ GCancellable *cancellable;
+
+ g_assert (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_assert (G_IS_TASK (main_task));
+
+ if (NULL == (changes = ide_code_index_builder_get_changes_finish (self, result, &error)))
+ {
+ g_message ("Failed to get file changes, %s", error->message);
+ g_task_return_error (main_task, g_steal_pointer (&error));
+ return;
+ }
+ else if (changes->len == 0)
+ {
+ g_debug ("No changes are there, completing task");
+ g_task_return_boolean (main_task, TRUE);
+ return;
+ }
+ else if (g_task_return_error_if_cancelled (main_task))
+ {
+ return;
+ }
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_context_get_build_system (context);
+ files = ide_code_index_builder_get_all_files (self, changes);
+ cancellable = g_task_get_cancellable (main_task);
+
+ g_message ("Getting build flags for %d directories", changes->len);
+
+ g_task_set_task_data (main_task,
+ g_steal_pointer (&changes),
+ (GDestroyNotify)g_ptr_array_unref);
+
+ /* TODO: add time out to finish task. This will help of build system fails to get flags */
+
+ ide_build_system_get_build_flags_for_files_async (build_system,
+ files,
+ cancellable,
+ ide_code_index_builder_build_cb2,
+ g_steal_pointer (&main_task));
+}
+
+/* This function will index a directory (recursively) and load that index */
+void
+ide_code_index_builder_build_async (IdeCodeIndexBuilder *self,
+ GFile *directory,
+ gboolean recursive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) main_task = NULL;
+
+ g_return_if_fail (IDE_IS_CODE_INDEX_BUILDER (self));
+ g_return_if_fail (G_IS_FILE (directory));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ g_debug ("Started building index");
+
+ main_task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (main_task, G_PRIORITY_LOW);
+ g_task_set_source_tag (main_task, ide_code_index_builder_build_async);
+
+ if (g_task_return_error_if_cancelled (main_task))
+ return;
+
+ ide_code_index_builder_get_changes_async (self,
+ directory,
+ recursive,
+ cancellable,
+ ide_code_index_builder_build_cb,
+ g_steal_pointer (&main_task));
+}
+
+gboolean
+ide_code_index_builder_build_finish (IdeCodeIndexBuilder *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *main_task = (GTask *)result;
+
+ g_return_val_if_fail (G_IS_TASK (main_task), FALSE);
+
+ return g_task_propagate_boolean (main_task, error);
+}
+
+static void
+ide_code_index_builder_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+
+ switch (prop_id)
+ {
+ case PROP_INDEX:
+ self->index = g_value_dup_object (value);
+ break;
+ case PROP_SERVICE:
+ self->service = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_code_index_builder_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+
+ switch (prop_id)
+ {
+ case PROP_INDEX:
+ g_value_set_object (value, self->index);
+ break;
+ case PROP_SERVICE:
+ g_value_set_object (value, self->service);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_code_index_builder_init (IdeCodeIndexBuilder *self)
+{
+ self->build_flags = g_hash_table_new_full ((GHashFunc)ide_file_hash,
+ (GEqualFunc)ide_file_equal,
+ g_object_unref,
+ (GDestroyNotify)g_strfreev);
+ g_mutex_init (&self->indexed);
+}
+
+static void
+ide_code_index_builder_finalize (GObject *object)
+{
+ IdeCodeIndexBuilder *self = (IdeCodeIndexBuilder *)object;
+
+ g_clear_object (&self->index);
+ g_clear_object (&self->service);
+ g_clear_pointer (&self->build_flags, g_hash_table_unref);
+ g_mutex_clear (&self->indexed);
+
+ G_OBJECT_CLASS(ide_code_index_builder_parent_class)->finalize (object);
+}
+
+static void
+ide_code_index_builder_class_init (IdeCodeIndexBuilderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = ide_code_index_builder_set_property;
+ object_class->get_property = ide_code_index_builder_get_property;
+ object_class->finalize = ide_code_index_builder_finalize;
+
+ properties [PROP_INDEX] =
+ g_param_spec_object ("index",
+ "Index",
+ "Index in which all symbols are stored.",
+ IDE_TYPE_CODE_INDEX_INDEX,
+ G_PARAM_READWRITE);
+
+ properties [PROP_SERVICE] =
+ g_param_spec_object ("service",
+ "Service",
+ "IdeCodeIndexService.",
+ IDE_TYPE_CODE_INDEX_SERVICE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+IdeCodeIndexBuilder *
+ide_code_index_builder_new (IdeContext *context,
+ IdeCodeIndexIndex *index,
+ IdeCodeIndexService *service)
+{
+ g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
+ g_return_val_if_fail (IDE_IS_CODE_INDEX_INDEX (index), NULL);
+
+ return g_object_new (IDE_TYPE_CODE_INDEX_BUILDER,
+ "context", context,
+ "index", index,
+ "service", service,
+ NULL);
+}
diff --git a/plugins/code-index/ide-code-index-builder.h b/plugins/code-index/ide-code-index-builder.h
new file mode 100644
index 0000000..ef06fba
--- /dev/null
+++ b/plugins/code-index/ide-code-index-builder.h
@@ -0,0 +1,48 @@
+/* ide-code-index-builder.h
+ *
+ * Copyright (C) 2017 Anoop Chandu <anoopchandu96 gmail 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/>.
+ */
+
+#ifndef IDE_CODE_INDEX_BUILDER_H
+#define IDE_CODE_INDEX_BUILDER_H
+
+#include <ide.h>
+
+#include "ide-code-index-index.h"
+#include "ide-code-index-service.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_CODE_INDEX_BUILDER (ide_code_index_builder_get_type ())
+
+G_DECLARE_FINAL_TYPE (IdeCodeIndexBuilder, ide_code_index_builder, IDE, CODE_INDEX_BUILDER, IdeObject)
+
+void ide_code_index_builder_build_async (IdeCodeIndexBuilder *self,
+ GFile *directory,
+ gboolean recursive,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_code_index_builder_build_finish (IdeCodeIndexBuilder *self,
+ GAsyncResult *result,
+ GError **error);
+IdeCodeIndexBuilder *ide_code_index_builder_new (IdeContext *context,
+ IdeCodeIndexIndex *index,
+ IdeCodeIndexService *service);
+
+G_END_DECLS
+
+#endif /* IDE_CODE_INDEX_BUILDER_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]