[gnome-builder] clang: stub out diagnose handler and test case
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] clang: stub out diagnose handler and test case
- Date: Fri, 20 Apr 2018 10:26:25 +0000 (UTC)
commit ec47bea6b6cc75456372469be64b0ab8db0419f4
Author: Christian Hergert <chergert redhat com>
Date: Fri Apr 20 03:26:14 2018 -0700
clang: stub out diagnose handler and test case
src/plugins/clang/gnome-builder-clang.c | 79 +++++++++++++++
src/plugins/clang/ide-clang.c | 171 ++++++++++++++++++++++++++++++++
src/plugins/clang/ide-clang.h | 9 ++
src/plugins/clang/test-daemon.c | 42 ++++++++
4 files changed, 301 insertions(+)
---
diff --git a/src/plugins/clang/gnome-builder-clang.c b/src/plugins/clang/gnome-builder-clang.c
index 7b776caa5..4d91a771d 100644
--- a/src/plugins/clang/gnome-builder-clang.c
+++ b/src/plugins/clang/gnome-builder-clang.c
@@ -242,6 +242,80 @@ handle_index_file (JsonrpcServer *server,
client_op_ref (op));
}
+/* Diagnose Handler {{{1 */
+
+static void
+handle_diagnose_cb (IdeClang *clang,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(ClientOp) op = user_data;
+ g_autoptr(GPtrArray) diagnostics = NULL;
+ g_autoptr(GError) error = NULL;
+ GVariantBuilder builder;
+
+ g_assert (IDE_IS_CLANG (clang));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (op != NULL);
+
+ if (!(diagnostics = ide_clang_diagnose_finish (clang, result, &error)))
+ {
+ client_op_error (op, error);
+ return;
+ }
+
+ IDE_PTR_ARRAY_SET_FREE_FUNC (diagnostics, ide_diagnostic_unref);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ for (guint i = 0; i < diagnostics->len; i++)
+ {
+ G_GNUC_UNUSED IdeDiagnostic *diag = g_ptr_array_index (diagnostics, i);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_close (&builder);
+ }
+
+ client_op_reply (op, g_variant_builder_end (&builder));
+}
+
+static void
+handle_diagnose (JsonrpcServer *server,
+ JsonrpcClient *client,
+ const gchar *method,
+ GVariant *id,
+ GVariant *params,
+ IdeClang *clang)
+{
+ g_autoptr(GPtrArray) argv = NULL;
+ g_autoptr(ClientOp) op = NULL;
+ g_auto(GStrv) flags = NULL;
+ const gchar *path = NULL;
+
+ g_assert (JSONRPC_IS_SERVER (server));
+ g_assert (JSONRPC_IS_CLIENT (client));
+ g_assert (g_str_equal (method, "clang/diagnose"));
+ g_assert (id != NULL);
+ g_assert (IDE_IS_CLANG (clang));
+
+ op = client_op_new (client, id);
+
+ if (!JSONRPC_MESSAGE_PARSE (params, "path", JSONRPC_MESSAGE_GET_STRING (&path)))
+ {
+ client_op_bad_params (op);
+ return;
+ }
+
+ JSONRPC_MESSAGE_PARSE (params, "flags", JSONRPC_MESSAGE_GET_STRV (&flags));
+
+ ide_clang_diagnose_async (clang,
+ path,
+ (const gchar * const *)flags,
+ op->cancellable,
+ (GAsyncReadyCallback)handle_diagnose_cb,
+ client_op_ref (op));
+}
+
/* Main and Server Setup {{{1 */
static void
@@ -303,6 +377,11 @@ main (gint argc,
(JsonrpcServerHandler)handle_index_file,
g_object_ref (clang),
g_object_unref);
+ jsonrpc_server_add_handler (server,
+ "clang/diagnose",
+ (JsonrpcServerHandler)handle_diagnose,
+ g_object_ref (clang),
+ g_object_unref);
jsonrpc_server_accept_io_stream (server, stream);
diff --git a/src/plugins/clang/ide-clang.c b/src/plugins/clang/ide-clang.c
index 651db352a..cf7014907 100644
--- a/src/plugins/clang/ide-clang.c
+++ b/src/plugins/clang/ide-clang.c
@@ -472,6 +472,177 @@ ide_clang_index_file_finish (IdeClang *self,
return ret;
}
+/* Diagnose {{{1 */
+
+typedef struct
+{
+ GPtrArray *diagnostics;
+ gchar *path;
+ gchar **argv;
+ guint argc;
+} Diagnose;
+
+static void
+diagnose_free (gpointer data)
+{
+ Diagnose *state = data;
+
+ g_clear_pointer (&state->path, g_free);
+ g_clear_pointer (&state->argv, g_strfreev);
+ g_clear_pointer (&state->diagnostics, g_ptr_array_unref);
+
+ g_slice_free (Diagnose, state);
+}
+
+static IdeDiagnostic *
+create_diagnostic (CXDiagnostic diag)
+{
+ g_assert (diag != NULL);
+
+
+ return NULL;
+}
+
+static void
+ide_clang_diagnose_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ Diagnose *state = task_data;
+ g_auto(CXTranslationUnit) unit = NULL;
+ g_auto(CXIndex) index = NULL;
+ enum CXErrorCode code;
+ unsigned options;
+ guint n_diags;
+
+ g_assert (IDE_IS_CLANG (source_object));
+ g_assert (IDE_IS_TASK (task));
+ g_assert (state != NULL);
+ g_assert (state->path != NULL);
+ g_assert (state->diagnostics != NULL);
+
+ options = (clang_defaultEditingTranslationUnitOptions () |
+#if CINDEX_VERSION >= CINDEX_VERSION_ENCODE(0, 43)
+ CXTranslationUnit_SingleFileParse |
+#endif
+#if CINDEX_VERSION >= CINDEX_VERSION_ENCODE(0, 35)
+ CXTranslationUnit_KeepGoing |
+#endif
+ CXTranslationUnit_DetailedPreprocessingRecord |
+ CXTranslationUnit_SkipFunctionBodies);
+
+ index = clang_createIndex (0, 0);
+ code = clang_parseTranslationUnit2 (index,
+ state->path,
+ (const char * const *)state->argv,
+ state->argc,
+ NULL,
+ 0,
+ options,
+ &unit);
+
+ if (code != CXError_Success)
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to index file \"%s\", exited with code %d",
+ state->path, code);
+ return;
+ }
+
+ n_diags = clang_getNumDiagnostics (unit);
+
+ for (guint i = 0; i < n_diags; i++)
+ {
+ g_autoptr(CXDiagnostic) cxdiag = NULL;
+ g_autoptr(IdeDiagnostic) diag = NULL;
+
+ cxdiag = clang_getDiagnostic (unit, i);
+ diag = create_diagnostic (cxdiag);
+
+ if (diag != NULL)
+ g_ptr_array_add (state->diagnostics, g_steal_pointer (&diag));
+ }
+
+ ide_task_return_pointer (task,
+ g_steal_pointer (&state->diagnostics),
+ (GDestroyNotify)g_ptr_array_unref);
+}
+
+/**
+ * ide_clang_diagnose_async:
+ * @self: a #IdeClang
+ * @path: the path to the C/C++/Obj-C file on local disk
+ * @argv: the command line arguments for clang
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute up on completion
+ * @user_data: closure data for @callback
+ *
+ * Asynchronously requests that the file be diagnosed.
+ *
+ * This generates diagnostics related to the file after parsing it.
+ *
+ * Since: 3.30
+ */
+void
+ide_clang_diagnose_async (IdeClang *self,
+ const gchar *path,
+ const gchar * const *argv,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ Diagnose *state;
+
+ g_return_if_fail (IDE_IS_CLANG (self));
+ g_return_if_fail (path != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ state = g_slice_new0 (Diagnose);
+ state->path = g_strdup (path);
+ state->argv = ide_clang_cook_flags (argv);
+ state->argc = state->argv ? g_strv_length (state->argv) : 0;
+ state->diagnostics = g_ptr_array_new ();
+
+ IDE_PTR_ARRAY_SET_FREE_FUNC (state->diagnostics, ide_diagnostic_unref);
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_clang_diagnose_async);
+ ide_task_set_kind (task, IDE_TASK_KIND_COMPILER);
+ ide_task_set_task_data (task, state, diagnose_free);
+ ide_task_run_in_thread (task, ide_clang_diagnose_worker);
+}
+
+/**
+ * ide_clang_diagnose_finish:
+ *
+ * Finishes a request to diagnose a file.
+ *
+ * Returns: (transfer full) (element-type Ide.Diagnostic):
+ * a #GPtrArray of #IdeDiagnostic
+ *
+ * Since: 3.30
+ */
+GPtrArray *
+ide_clang_diagnose_finish (IdeClang *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GPtrArray *ret;
+
+ g_return_val_if_fail (IDE_IS_CLANG (self), NULL);
+ g_return_val_if_fail (IDE_IS_TASK (result), NULL);
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_PTR_ARRAY_CLEAR_FREE_FUNC (ret);
+
+ return ret;
+}
+
/* Get symbol at source location {{{1 */
/* vim:set foldmethod=marker: */
diff --git a/src/plugins/clang/ide-clang.h b/src/plugins/clang/ide-clang.h
index 8a38c4f04..739be0114 100644
--- a/src/plugins/clang/ide-clang.h
+++ b/src/plugins/clang/ide-clang.h
@@ -36,5 +36,14 @@ void ide_clang_index_file_async (IdeClang *self,
GPtrArray *ide_clang_index_file_finish (IdeClang *self,
GAsyncResult *result,
GError **error);
+void ide_clang_diagnose_async (IdeClang *self,
+ const gchar *path,
+ const gchar * const *argv,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPtrArray *ide_clang_diagnose_finish (IdeClang *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/plugins/clang/test-daemon.c b/src/plugins/clang/test-daemon.c
index 70b92b7ba..d9b3b54a0 100644
--- a/src/plugins/clang/test-daemon.c
+++ b/src/plugins/clang/test-daemon.c
@@ -8,6 +8,8 @@ typedef void (*TestFunc) (JsonrpcClient *client,
GTask *task);
static void tick_tests (JsonrpcClient *client);
+static void test_diagnose (JsonrpcClient *client,
+ GTask *task);
static void test_index_file (JsonrpcClient *client,
GTask *task);
@@ -15,6 +17,7 @@ static gchar **flags;
static const gchar *path;
static GMainLoop *main_loop;
static TestFunc test_funcs[] = {
+ test_diagnose,
test_index_file,
};
@@ -57,6 +60,45 @@ test_index_file (JsonrpcClient *client,
g_object_ref (task));
}
+static void
+test_diagnose_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ JsonrpcClient *client = (JsonrpcClient *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_TASK (task));
+
+ if (!jsonrpc_client_call_finish (client, result, &reply, &error))
+ g_error ("diagnose: %s", error->message);
+
+ g_printerr ("diagnose: %s\n", g_variant_print (reply, TRUE));
+
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+test_diagnose (JsonrpcClient *client,
+ GTask *task)
+{
+ g_autoptr(GVariant) params = NULL;
+
+ params = JSONRPC_MESSAGE_NEW (
+ "path", JSONRPC_MESSAGE_PUT_STRING (path),
+ "flags", JSONRPC_MESSAGE_PUT_STRV ((const gchar * const *)flags)
+ );
+
+ jsonrpc_client_call_async (client,
+ "clang/diagnose",
+ params,
+ NULL,
+ test_diagnose_cb,
+ g_object_ref (task));
+}
+
static void
finished_cb (GObject *object,
GAsyncResult *result,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]