[gnome-builder/wip/chergert/clang] clang: add buffer sync to daemon helpers
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/clang] clang: add buffer sync to daemon helpers
- Date: Fri, 27 Apr 2018 02:17:38 +0000 (UTC)
commit 55f7dff49db5c6142da98d7e65382fe0194eff58
Author: Christian Hergert <chergert redhat com>
Date: Thu Apr 26 18:37:55 2018 -0700
clang: add buffer sync to daemon helpers
src/plugins/clang/ide-clang-client.c | 122 +++++++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
---
diff --git a/src/plugins/clang/ide-clang-client.c b/src/plugins/clang/ide-clang-client.c
index 5f19e444d..10d197146 100644
--- a/src/plugins/clang/ide-clang-client.c
+++ b/src/plugins/clang/ide-clang-client.c
@@ -35,6 +35,7 @@ struct _IdeClangClient
IdeSubprocessSupervisor *supervisor;
JsonrpcClient *rpc_client;
GFile *root_uri;
+ GHashTable *seq_by_file;
gint state;
};
@@ -64,6 +65,71 @@ call_free (gpointer data)
g_slice_free (Call, c);
}
+static void
+ide_clang_client_sync_buffers (IdeClangClient *self)
+{
+ g_autoptr(GPtrArray) ar = NULL;
+ IdeContext *context;
+ IdeUnsavedFiles *ufs;
+
+ g_assert (IDE_IS_CLANG_CLIENT (self));
+
+ /*
+ * We need to sync buffers to the subprocess, but only those that are of any
+ * consequence to us. So that means C, C++, or Obj-C files and headers.
+ *
+ * Further more, to avoid the chatter, we only want to send updated buffers
+ * for unsaved files which we have not already sent or we'll be way too
+ * chatty and cancel any cached translation units the subprocess has.
+ *
+ * Since the subprocess processes commands in order, we can simply call the
+ * function to set the buffer on the peer and ignore the result (and it will
+ * be used on subsequence commands).
+ */
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ ufs = ide_context_get_unsaved_files (context);
+ ar = ide_unsaved_files_to_array (ufs);
+ IDE_PTR_ARRAY_SET_FREE_FUNC (ar, ide_unsaved_file_unref);
+
+ if (self->seq_by_file == NULL)
+ self->seq_by_file = g_hash_table_new_full (g_file_hash,
+ (GEqualFunc)g_file_equal,
+ g_object_unref,
+ NULL);
+
+ for (guint i = 0; i < ar->len; i++)
+ {
+ IdeUnsavedFile *uf = g_ptr_array_index (ar, i);
+ GFile *file = ide_unsaved_file_get_file (uf);
+ gsize seq = (gsize)ide_unsaved_file_get_sequence (uf);
+ gsize prev = GPOINTER_TO_SIZE (g_hash_table_lookup (self->seq_by_file, file));
+ g_autofree gchar *name = g_file_get_basename (file);
+ const gchar *dot = strrchr (name, '.');
+
+ if (seq <= prev)
+ continue;
+
+ if (dot == NULL || !(g_str_equal (dot, ".c") ||
+ g_str_equal (dot, ".h") ||
+ g_str_equal (dot, ".cc") ||
+ g_str_equal (dot, ".hh") ||
+ g_str_equal (dot, ".cpp") ||
+ g_str_equal (dot, ".hpp") ||
+ g_str_equal (dot, ".cxx") ||
+ g_str_equal (dot, ".hxx") ||
+ g_str_equal (dot, ".m")))
+ continue;
+
+ g_hash_table_insert (self->seq_by_file, g_object_ref (file), GSIZE_TO_POINTER (seq));
+
+ ide_clang_client_set_buffer_async (self,
+ file,
+ ide_unsaved_file_get_content (uf),
+ NULL, NULL, NULL);
+ }
+}
+
static void
ide_clang_client_subprocess_exited (IdeClangClient *self,
IdeSubprocess *subprocess,
@@ -78,6 +144,8 @@ ide_clang_client_subprocess_exited (IdeClangClient *self,
if (self->state == STATE_RUNNING)
self->state = STATE_SPAWNING;
+ g_clear_pointer (&self->seq_by_file, g_hash_table_unref);
+
IDE_EXIT;
}
@@ -207,17 +275,50 @@ ide_clang_client_get_client_finish (IdeClangClient *self,
return ide_task_propagate_object (IDE_TASK (result), error);
}
+static void
+ide_clang_client_buffer_saved (IdeClangClient *self,
+ IdeBuffer *buffer,
+ IdeBufferManager *bufmgr)
+{
+ IdeFile *file;
+ GFile *gfile;
+
+ g_assert (IDE_IS_CLANG_CLIENT (self));
+ g_assert (IDE_BUFFER (buffer));
+ g_assert (IDE_BUFFER_MANAGER (bufmgr));
+
+ /*
+ * We need to clear the cached buffer on the peer (and potentially
+ * pop the translation unit cache) now that the buffer has been
+ * saved to disk and we no longer need the draft.
+ */
+
+ file = ide_buffer_get_file (buffer);
+ gfile = ide_file_get_file (file);
+ if (self->seq_by_file != NULL)
+ g_hash_table_remove (self->seq_by_file, gfile);
+
+ /* skip if thereis no peer */
+ if (self->rpc_client == NULL)
+ return;
+
+ if (gfile != NULL)
+ ide_clang_client_set_buffer_async (self, gfile, NULL, NULL, NULL, NULL);
+}
+
static void
ide_clang_client_constructed (GObject *object)
{
IdeClangClient *self = (IdeClangClient *)object;
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
g_autofree gchar *cwd = NULL;
+ IdeBufferManager *bufmgr;
IdeContext *context;
IdeVcs *vcs;
GFile *workdir;
context = ide_object_get_context (IDE_OBJECT (self));
+ bufmgr = ide_context_get_buffer_manager (context);
vcs = ide_context_get_vcs (context);
workdir = ide_vcs_get_working_directory (vcs);
@@ -251,6 +352,12 @@ ide_clang_client_constructed (GObject *object)
self,
G_CONNECT_SWAPPED);
+ g_signal_connect_object (bufmgr,
+ "buffer-saved",
+ G_CALLBACK (ide_clang_client_buffer_saved),
+ self,
+ G_CONNECT_SWAPPED);
+
G_OBJECT_CLASS (ide_clang_client_parent_class)->constructed (object);
}
@@ -297,6 +404,7 @@ ide_clang_client_finalize (GObject *object)
{
IdeClangClient *self = (IdeClangClient *)object;
+ g_clear_pointer (&self->seq_by_file, g_hash_table_unref);
g_clear_object (&self->rpc_client);
g_clear_object (&self->root_uri);
g_clear_object (&self->supervisor);
@@ -576,6 +684,8 @@ ide_clang_client_get_index_key_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -669,6 +779,8 @@ ide_clang_client_find_nearest_scope_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -762,6 +874,8 @@ ide_clang_client_locate_symbol_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -845,6 +959,8 @@ ide_clang_client_get_symbol_tree_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -940,6 +1056,8 @@ ide_clang_client_diagnose_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -1017,6 +1135,8 @@ ide_clang_client_get_highlight_index_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
@@ -1094,6 +1214,8 @@ ide_clang_client_complete_async (IdeClangClient *self,
return;
}
+ ide_clang_client_sync_buffers (self);
+
path = g_file_get_path (file);
params = JSONRPC_MESSAGE_NEW (
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]