[gnome-builder/wip/code-assistance] code-assistance: highlight error regions from code assistance



commit 405c6a5f6f992dd19ec0be33f7c6756f8590200d
Author: Christian Hergert <christian hergert me>
Date:   Sun Oct 19 22:18:17 2014 -0700

    code-assistance: highlight error regions from code assistance
    
    Still *tons* to do here, but at least you see squiggly lines now!

 src/editor/gb-editor-code-assistant.c |  138 +++++++++++++++++++++++++++++----
 src/editor/gb-editor-tab.c            |    3 -
 src/gca/gca-structs.c                 |  105 +++++++++++++++++++++++++
 src/gca/gca-structs.h                 |   67 ++++++++++++++++
 src/gnome-builder.mk                  |    2 +
 5 files changed, 295 insertions(+), 20 deletions(-)
---
diff --git a/src/editor/gb-editor-code-assistant.c b/src/editor/gb-editor-code-assistant.c
index f4adb8d..1ff5081 100644
--- a/src/editor/gb-editor-code-assistant.c
+++ b/src/editor/gb-editor-code-assistant.c
@@ -25,35 +25,142 @@
 #include "gb-log.h"
 #include "gca-diagnostics.h"
 #include "gca-service.h"
+#include "gca-structs.h"
 
 #define PARSE_TIMEOUT_MSEC 250
 
 static void
+add_diagnostic_range (GbEditorTab    *tab,
+                      GcaDiagnostic  *diag,
+                      GcaSourceRange *range)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter begin;
+  GtkTextIter end;
+  guint column;
+
+  g_assert (GB_IS_EDITOR_TAB (tab));
+  g_assert (diag);
+  g_assert (range);
+
+  buffer = GTK_TEXT_BUFFER (tab->priv->document);
+
+  gtk_text_buffer_get_iter_at_line (buffer, &begin, range->begin.line);
+  for (column = range->begin.column; column; column--)
+    if (gtk_text_iter_ends_line (&begin) || !gtk_text_iter_forward_char (&begin))
+      break;
+
+  gtk_text_buffer_get_iter_at_line (buffer, &end, range->end.line);
+  for (column = range->end.column; column; column--)
+    if (gtk_text_iter_ends_line (&end) || !gtk_text_iter_forward_char (&end))
+      break;
+
+  if (gtk_text_iter_equal (&begin, &end))
+    gtk_text_iter_forward_to_line_end (&end);
+
+  gtk_text_buffer_apply_tag_by_name (buffer, "ErrorTag", &begin, &end);
+}
+
+static void
+add_diagnostic (GbEditorTab   *tab,
+                GcaDiagnostic *diag)
+{
+  guint i;
+
+  g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+  g_return_if_fail (diag);
+
+#if 0
+  g_print ("DIAG: %s\n", diag->message);
+#endif
+
+  for (i = 0; i < diag->locations->len; i++)
+    {
+      GcaSourceRange *range;
+
+      range = &g_array_index (diag->locations, GcaSourceRange, i);
+      add_diagnostic_range (tab, diag, range);
+    }
+}
+
+static const gchar *
+get_language (GbSourceView *view)
+{
+  GtkTextBuffer *buffer;
+  GtkSourceLanguage *lang;
+  const gchar *lang_id;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+  if (!GTK_SOURCE_IS_BUFFER (buffer))
+    return NULL;
+
+  lang = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer));
+  if (!lang)
+    return NULL;
+
+  /* TODO: probably should get the mapping from GCA service for this */
+  lang_id = gtk_source_language_get_id (lang);
+  if (g_str_equal (lang_id, "chdr") || g_str_equal (lang_id, "objc"))
+    return "c";
+
+  return lang_id;
+}
+
+static void
 gb_editor_code_assistant_diag_cb (GObject      *source_object,
                                   GAsyncResult *result,
                                   gpointer      user_data)
 {
   GbEditorTab *tab = user_data;
-  GcaDiagnostics *diag = (GcaDiagnostics *)source_object;
+  GtkTextBuffer *buffer;
+  GtkTextTagTable *tag_table;
+  GtkTextIter begin;
+  GtkTextIter end;
+  GtkTextTag *tag;
+  GcaDiagnostics *proxy = (GcaDiagnostics *)source_object;
   GVariant *diags = NULL;
+  GArray *ar;
   GError *error = NULL;
+  guint i;
 
-  if (!gca_diagnostics_call_diagnostics_finish (diag, &diags, result, &error))
+  ENTRY;
+
+  if (!gca_diagnostics_call_diagnostics_finish (proxy, &diags, result, &error))
     {
       g_warning ("%s", error->message);
       g_clear_error (&error);
       GOTO (cleanup);
     }
 
-  {
-    gchar *str = g_variant_print (diags, TRUE);
-    g_print (">> %s\n", str);
-    g_free (str);
-  }
+  buffer = GTK_TEXT_BUFFER (tab->priv->document);
+  tag_table = gtk_text_buffer_get_tag_table (buffer);
+  tag = gtk_text_tag_table_lookup (tag_table, "ErrorTag");
+
+  if (!tag)
+    tag = gtk_text_buffer_create_tag (buffer, "ErrorTag",
+                                      "underline", PANGO_UNDERLINE_ERROR,
+                                      NULL);
+
+  gtk_text_buffer_get_bounds (buffer, &begin, &end);
+  gtk_text_buffer_remove_tag (buffer, tag, &begin, &end);
+
+  ar = gca_diagnostics_from_variant (diags);
+
+  for (i = 0; i < ar->len; i++)
+    {
+      GcaDiagnostic *diag;
+
+      diag = &g_array_index (ar, GcaDiagnostic, i);
+      add_diagnostic (tab, diag);
+    }
+
+  g_array_unref (ar);
 
 cleanup:
   g_clear_pointer (&diags, g_variant_unref);
   g_object_unref (tab);
+
+  EXIT;
 }
 
 static void
@@ -64,7 +171,6 @@ gb_editor_code_assistant_parse_cb (GObject      *source_object,
   GbEditorTab *tab = user_data;
   GcaService *service = (GcaService *)source_object;
   GcaDiagnostics *diag_proxy = NULL;
-  GtkSourceLanguage *language;
   const gchar *lang_id;
   GError *error = NULL;
   gchar *document_path = NULL;
@@ -82,12 +188,10 @@ gb_editor_code_assistant_parse_cb (GObject      *source_object,
       GOTO (cleanup);
     }
 
-  language =
-    gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (tab->priv->document));
-  if (!language)
+  lang_id = get_language (tab->priv->source_view);
+  if (!lang_id)
     GOTO (cleanup);
 
-  lang_id = gtk_source_language_get_id (language);
   name = g_strdup_printf ("org.gnome.CodeAssist.v1.%s", lang_id);
 
   diag_proxy =
@@ -129,6 +233,8 @@ gb_editor_code_assistant_parse (gpointer user_data)
   gchar *path;
   gchar *text;
 
+  ENTRY;
+
   g_return_val_if_fail (GB_IS_EDITOR_TAB (tab), G_SOURCE_REMOVE);
 
   priv = tab->priv;
@@ -163,7 +269,7 @@ gb_editor_code_assistant_parse (gpointer user_data)
   g_free (path);
   g_free (text);
 
-  return G_SOURCE_REMOVE;
+  RETURN (G_SOURCE_REMOVE);
 }
 
 static void
@@ -198,7 +304,6 @@ void
 gb_editor_code_assistant_init (GbEditorTab *tab)
 {
   GbEditorTabPrivate *priv;
-  GtkSourceLanguage *language;
   const gchar *lang_id;
   gchar *name;
   gchar *path;
@@ -210,11 +315,10 @@ gb_editor_code_assistant_init (GbEditorTab *tab)
 
   priv = tab->priv;
 
-  language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (priv->document));
-  if (!language)
+  lang_id = get_language (tab->priv->source_view);
+  if (!lang_id)
     EXIT;
 
-  lang_id = gtk_source_language_get_id (language);
   name = g_strdup_printf ("org.gnome.CodeAssist.v1.%s", lang_id);
   path = g_strdup_printf ("/org/gnome/CodeAssist/v1/%s", lang_id);
 
diff --git a/src/editor/gb-editor-tab.c b/src/editor/gb-editor-tab.c
index c6541ee..d077428 100644
--- a/src/editor/gb-editor-tab.c
+++ b/src/editor/gb-editor-tab.c
@@ -1086,9 +1086,6 @@ transform_file_to_language (GBinding     *binding,
           settings = gb_editor_settings_new_for_language (lang_id);
           gb_editor_tab_set_settings (tab, settings);
           g_object_unref (settings);
-
-          
-          gb_editor_code_assistant_init (tab);
         }
 
       g_free (filename);
diff --git a/src/gca/gca-structs.c b/src/gca/gca-structs.c
new file mode 100644
index 0000000..c8ab4b7
--- /dev/null
+++ b/src/gca/gca-structs.c
@@ -0,0 +1,105 @@
+/* gca-structs.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "gb-log.h"
+#include "gca-structs.h"
+
+static void
+gca_diagnostic_destroy (gpointer data)
+{
+  GcaDiagnostic *diag = data;
+
+  if (diag)
+    {
+      g_array_unref (diag->fixits);
+      g_array_unref (diag->locations);
+      g_free (diag->message);
+    }
+}
+
+static void
+gca_fixit_destroy (gpointer data)
+{
+  GcaFixit *fixit = data;
+
+  if (fixit)
+    g_free (fixit->value);
+}
+
+GArray *
+gca_diagnostics_from_variant (GVariant *variant)
+{
+  GVariantIter iter;
+  GArray *ret;
+  GVariantIter *b;
+  GVariantIter *c;
+  gchar *d;
+  guint a;
+
+  ret = g_array_new (FALSE, FALSE, sizeof (GcaDiagnostic));
+
+  g_array_set_clear_func (ret, gca_diagnostic_destroy);
+
+  g_variant_iter_init (&iter, variant);
+
+  while (g_variant_iter_loop (&iter, "(ua((x(xx)(xx))s)a(x(xx)(xx))s)",
+                              &a, &b, &c, &d))
+    {
+      GcaDiagnostic diag = { 0 };
+      gint64 x1, x2, x3, x4, x5;
+      gchar *e;
+
+      diag.severity = a;
+      diag.fixits = g_array_new (FALSE, FALSE, sizeof (GcaFixit));
+      diag.locations = g_array_new (FALSE, FALSE, sizeof (GcaSourceRange));
+      diag.message = g_strdup (d);
+
+      g_array_set_clear_func (diag.fixits, gca_fixit_destroy);
+
+      while (g_variant_iter_next (b, "((x(xx)(xx))s)", &x1, &x2, &x3, &x4, &x5, &e))
+        {
+          GcaFixit fixit = {{ 0 }};
+
+          fixit.range.file = x1;
+          fixit.range.begin.line = x2 - 1;
+          fixit.range.begin.column = x3 - 1;
+          fixit.range.end.line = x4 - 1;
+          fixit.range.end.column = x5 - 1;
+          fixit.value = g_strdup (e);
+
+          g_array_append_val (diag.fixits, fixit);
+        }
+
+      while (g_variant_iter_next (c, "(x(xx)(xx))", &x1, &x2, &x3, &x4, &x5))
+        {
+          GcaSourceRange range = { 0 };
+
+          range.file = x1;
+          range.begin.line = x2 - 1;
+          range.begin.column = x3 - 1;
+          range.end.line = x4 - 1;
+          range.end.column = x5 - 1;
+
+          g_array_append_val (diag.locations, range);
+        }
+
+      g_array_append_val (ret, diag);
+    }
+
+  return ret;
+}
diff --git a/src/gca/gca-structs.h b/src/gca/gca-structs.h
new file mode 100644
index 0000000..57b8219
--- /dev/null
+++ b/src/gca/gca-structs.h
@@ -0,0 +1,67 @@
+/* gca-structs.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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 GCA_STRUCTS_H
+#define GCA_STRUCTS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  GCA_SEVERITY_NONE,
+  GCA_SEVERITY_INFO,
+  GCA_SEVERITY_WARNING,
+  GCA_SEVERITY_DEPRECATED,
+  GCA_SEVERITY_ERROR,
+  GCA_SEVERITY_FATAL,
+} GcaSeverity;
+
+typedef struct
+{
+  guint64 line;
+  guint64 column;
+} GcaSourceLocation;
+
+typedef struct
+{
+  gint64            file;
+  GcaSourceLocation begin;
+  GcaSourceLocation end;
+} GcaSourceRange;
+
+typedef struct
+{
+  GcaSourceRange  range;
+  gchar          *value;
+} GcaFixit;
+
+typedef struct
+{
+  GcaSeverity  severity;
+  GArray      *fixits;
+  GArray      *locations;
+  gchar       *message;
+} GcaDiagnostic;
+
+GArray *gca_diagnostics_from_variant (GVariant *variant);
+
+G_END_DECLS
+
+#endif /* GCA_STRUCTS_H */
diff --git a/src/gnome-builder.mk b/src/gnome-builder.mk
index 756a0e6..c14c415 100644
--- a/src/gnome-builder.mk
+++ b/src/gnome-builder.mk
@@ -81,6 +81,8 @@ libgnome_builder_la_SOURCES = \
        src/gca/gca-diagnostics.h \
        src/gca/gca-service.c \
        src/gca/gca-service.h \
+       src/gca/gca-structs.c \
+       src/gca/gca-structs.h \
        src/markdown/gs-markdown.c \
        src/markdown/gs-markdown.h \
        src/markdown/gb-markdown-preview.c \


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