[gnome-builder] code-indexer: pre-filter files by supported indexers



commit a8a0ef010624469bd8f2b28e04926b17247f6a0e
Author: Christian Hergert <chergert redhat com>
Date:   Sat Jan 27 00:35:41 2018 -0800

    code-indexer: pre-filter files by supported indexers
    
    We want to generate our list of files to update on a worker
    thread, but to do that accurately we need to know about what
    indexers are supported. Accessing that data requires information
    only accessible from the main thread.
    
    To ensure we can stay threaded and perform that check safely,
    we make a copy of the indexer information and proxy that to our
    worker thread along with the other exclusive state.
    
    This fixes #366

 src/plugins/code-index/ide-code-index-builder.c | 149 +++++++++++++++++++++---
 1 file changed, 134 insertions(+), 15 deletions(-)
---
diff --git a/src/plugins/code-index/ide-code-index-builder.c b/src/plugins/code-index/ide-code-index-builder.c
index 6ef7ec75d..f1314f7a4 100644
--- a/src/plugins/code-index/ide-code-index-builder.c
+++ b/src/plugins/code-index/ide-code-index-builder.c
@@ -55,21 +55,29 @@ typedef struct
 
 typedef struct
 {
-  guint   magic;
-  GFile  *data_dir;
-  GFile  *index_dir;
-  IdeVcs *vcs;
-  GQueue  directories;
-  guint   recursive : 1;
+  GPtrArray *specs;
+  GPtrArray *mime_types;
+} IndexerInfo;
+
+typedef struct
+{
+  guint        magic;
+  GFile       *data_dir;
+  GFile       *index_dir;
+  IdeVcs      *vcs;
+  IndexerInfo *indexers;
+  GQueue       directories;
+  guint        recursive : 1;
 } GetChangesData;
 
 typedef struct
 {
-  guint      magic;
-  GFile     *directory;
-  gchar     *name;
-  GTimeVal   mtime;
-  GFileType  file_type;
+  guint        magic;
+  GFile       *directory;
+  gchar       *name;
+  const gchar *content_type;
+  GTimeVal     mtime;
+  GFileType    file_type;
 } FileInfo;
 
 typedef struct
@@ -116,9 +124,17 @@ build_data_free (BuildData *self)
 }
 
 static void
-get_changes_data_free (GetChangesData *self)
+indexer_info_free (IndexerInfo *info)
 {
+  g_clear_pointer (&info->specs, g_ptr_array_unref);
+  g_clear_pointer (&info->mime_types, g_ptr_array_unref);
+  g_slice_free (IndexerInfo, info);
+}
 
+static void
+get_changes_data_free (GetChangesData *self)
+{
+  g_clear_pointer (&self->indexers, indexer_info_free);
   g_clear_object (&self->data_dir);
   g_clear_object (&self->index_dir);
   g_clear_object (&self->vcs);
@@ -158,6 +174,102 @@ index_directory_data_free (IndexDirectoryData *self)
   g_slice_free (IndexDirectoryData, self);
 }
 
+static IndexerInfo *
+collect_indexer_info (void)
+{
+  GtkSourceLanguageManager *manager;
+  const GList *plugins;
+  PeasEngine *engine;
+  IndexerInfo *info;
+
+  manager = gtk_source_language_manager_get_default ();
+  engine = peas_engine_get_default ();
+  plugins = peas_engine_get_plugin_list (engine);
+
+  info = g_slice_new0 (IndexerInfo);
+  info->specs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_pattern_spec_free);
+  info->mime_types = g_ptr_array_new ();
+
+  for (; plugins != NULL; plugins = plugins->next)
+    {
+      const PeasPluginInfo *plugin_info = plugins->data;
+      g_auto(GStrv) split = NULL;
+      const gchar *str;
+
+      if (!peas_plugin_info_is_loaded (plugin_info))
+        continue;
+
+      if (!(str = peas_plugin_info_get_external_data (plugin_info, "Code-Indexer-Languages")))
+        continue;
+
+      split = g_strsplit (str, ",", 0);
+
+      for (guint i = 0; split[i] != NULL; i++)
+        {
+          const gchar *name = split[i];
+          GtkSourceLanguage *lang;
+          g_auto(GStrv) globs = NULL;
+          g_auto(GStrv) mime_types = NULL;
+
+          if (!(lang = gtk_source_language_manager_get_language (manager, name)))
+            continue;
+
+          globs = gtk_source_language_get_globs (lang);
+          mime_types = gtk_source_language_get_mime_types (lang);
+
+          for (guint j = 0; globs[j] != NULL; j++)
+            {
+              g_autoptr(GPatternSpec) spec = g_pattern_spec_new (globs[j]);
+              g_ptr_array_add (info->specs, g_steal_pointer (&spec));
+            }
+
+          for (guint j = 0; mime_types[j]; j++)
+            g_ptr_array_add (info->mime_types, (gchar *)g_intern_string (mime_types[j]));
+        }
+    }
+
+  return info;
+}
+
+static gboolean
+has_supported_indexer (const IndexerInfo *info,
+                       const gchar       *filename,
+                       const gchar       *mime_type)
+{
+  g_autofree gchar *reversed = NULL;
+  guint len;
+
+  g_assert (info != NULL);
+  g_assert (info->specs != NULL);
+  g_assert (info->mime_types != NULL);
+  g_assert (filename != NULL);
+
+  if (mime_type != NULL)
+    {
+      for (guint i = 0; i < info->mime_types->len; i++)
+        {
+          const gchar *mt = g_ptr_array_index (info->mime_types, i);
+
+          /* interned strings use pointer comparison */
+          if (mt == mime_type)
+            return TRUE;
+        }
+    }
+
+  len = strlen (filename);
+  reversed = g_utf8_strreverse (filename, len);
+
+  for (guint i = 0; i < info->specs->len; i++)
+    {
+      GPatternSpec *spec = g_ptr_array_index (info->specs, i);
+
+      if (g_pattern_match (spec, len, filename, reversed))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 static gint
 timeval_compare (const GTimeVal *a,
                  const GTimeVal *b)
@@ -385,8 +497,9 @@ directory_needs_update (GFile        *index_dir,
 }
 
 static void
-filter_ignored (IdeVcs *vcs,
-                GQueue *file_infos)
+filter_ignored (IdeVcs            *vcs,
+                GQueue            *file_infos,
+                const IndexerInfo *indexers)
 {
   g_assert (IDE_IS_VCS (vcs));
   g_assert (file_infos != NULL);
@@ -406,6 +519,9 @@ filter_ignored (IdeVcs *vcs,
       ignore = ide_vcs_is_ignored (vcs, file, NULL);
       g_clear_object (&file);
 
+      if (!ignore)
+        ignore = !has_supported_indexer (indexers, info->name, info->content_type);
+
       if (ignore)
         {
           GList *tmp = iter->next;
@@ -436,6 +552,7 @@ find_all_files_typed (GFile        *root,
   enumerator = g_file_enumerate_children (root,
                                           G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK","
                                           G_FILE_ATTRIBUTE_STANDARD_NAME","
+                                          G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
                                           G_FILE_ATTRIBUTE_STANDARD_TYPE","
                                           G_FILE_ATTRIBUTE_TIME_MODIFIED,
                                           G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
@@ -471,6 +588,7 @@ find_all_files_typed (GFile        *root,
           fi->directory = g_object_ref (root);
           fi->name = g_strdup (g_file_info_get_name (info));
           fi->file_type = g_file_info_get_file_type (info);
+          fi->content_type = g_intern_string (g_file_info_get_content_type (info));
           g_file_info_get_modification_time (info, &fi->mtime);
 
           func (g_steal_pointer (&fi), user_data);
@@ -584,7 +702,7 @@ get_changes_worker (GTask        *task,
                             get_changes_collect_files_cb,
                             &files);
 
-      filter_ignored (gcd->vcs, &files);
+      filter_ignored (gcd->vcs, &files, gcd->indexers);
 
       if (!(relative = g_file_get_relative_path (gcd->index_dir, dir)))
         index_dir = g_object_ref (gcd->index_dir);
@@ -658,6 +776,7 @@ get_changes_async (IdeCodeIndexBuilder *self,
 
   gcd = g_slice_new0 (GetChangesData);
   gcd->magic = GET_CHANGES_MAGIC;
+  gcd->indexers = collect_indexer_info ();
   gcd->data_dir = g_object_ref (data_dir);
   gcd->index_dir = g_object_ref (index_dir);
   gcd->recursive = !!recursive;


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