[gnome-builder] libide: various completion work



commit f09a474ad94a2df1031411cc4c7c62c2dbae76f0
Author: Christian Hergert <christian hergert me>
Date:   Mon Mar 16 00:17:25 2015 -0700

    libide: various completion work
    
    This progresses us towards using snippets when inserting completion
    items. Still lots to do, of course.

 libide/clang/ide-clang-completion-item.c     |  432 +++++++++++++++++++-------
 libide/clang/ide-clang-completion-item.h     |   18 +-
 libide/clang/ide-clang-completion-provider.c |   51 +++-
 3 files changed, 384 insertions(+), 117 deletions(-)
---
diff --git a/libide/clang/ide-clang-completion-item.c b/libide/clang/ide-clang-completion-item.c
index 694632c..4543ae1 100644
--- a/libide/clang/ide-clang-completion-item.c
+++ b/libide/clang/ide-clang-completion-item.c
@@ -16,12 +16,16 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define G_LOG_DOMAIN "ide-clang-completion"
+
 #include <clang-c/Index.h>
 #include <glib/gi18n.h>
-#include <gtksourceview/gtksourcecompletionproposal.h>
 
 #include "ide-clang-completion-item.h"
+#include "ide-debug.h"
 #include "ide-ref-ptr.h"
+#include "ide-source-snippet.h"
+#include "ide-source-snippet-chunk.h"
 
 struct _IdeClangCompletionItemClass
 {
@@ -30,39 +34,238 @@ struct _IdeClangCompletionItemClass
 
 struct _IdeClangCompletionItem
 {
-  GObject    parent_instance;
+  GObject           parent_instance;
+
+  guint             index;
+  gint              typed_text_index;
+  guint             initialized : 1;
 
-  IdeRefPtr *results;
-  guint      index;
+  gchar            *markup;
+  GdkPixbuf        *icon;
+  IdeRefPtr        *results;
+  IdeSourceSnippet *snippet;
 };
 
-enum
-{
+static void completion_proposal_iface_init (GtkSourceCompletionProposalIface *);
+
+G_DEFINE_TYPE_WITH_CODE (IdeClangCompletionItem, ide_clang_completion_item, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL,
+                                                completion_proposal_iface_init))
+
+enum {
   PROP_0,
   PROP_INDEX,
   PROP_RESULTS,
   LAST_PROP
 };
 
-static void completion_proposal_iface_init (GtkSourceCompletionProposalIface *);
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static CXCompletionResult *
+ide_clang_completion_item_get_result (IdeClangCompletionItem *self)
+{
+  CXCodeCompleteResults *results;
 
-G_DEFINE_TYPE_EXTENDED (IdeClangCompletionItem, ide_clang_completion_item, G_TYPE_OBJECT, 0,
-                        G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_COMPLETION_PROPOSAL,
-                                               completion_proposal_iface_init))
+  g_assert (IDE_IS_CLANG_COMPLETION_ITEM (self));
 
-static GParamSpec *gParamSpecs [LAST_PROP];
+  results = ide_ref_ptr_get (self->results);
+  return &results->Results [self->index];
+}
+
+static void
+ide_clang_completion_item_lazy_init (IdeClangCompletionItem *self)
+{
+  CXCompletionResult *result;
+  g_autoptr(IdeSourceSnippet) snippet = NULL;
+  GString *markup = NULL;
+  unsigned num_chunks;
+  unsigned i;
+  guint tab_stop = 0;
+
+  g_assert (IDE_IS_CLANG_COMPLETION_ITEM (self));
+
+  if (G_LIKELY (self->initialized))
+    return;
+
+  result = ide_clang_completion_item_get_result (self);
+  num_chunks = clang_getNumCompletionChunks (result);
+  snippet = ide_source_snippet_new (NULL, NULL);
+  markup = g_string_new (NULL);
+
+  g_assert (result);
+  g_assert (num_chunks);
+  g_assert (IDE_IS_SOURCE_SNIPPET (snippet));
+  g_assert (markup);
+
+  /*
+   * Walk the chunks, creating our snippet for insertion as well as our markup
+   * for the row in the completion window.
+   */
+  for (i = 0; i < num_chunks; i++)
+    {
+      enum CXCompletionChunkKind kind;
+      IdeSourceSnippetChunk *chunk;
+      const gchar *text;
+      g_autofree gchar *escaped = NULL;
+      CXString cxstr;
+
+      kind = clang_getCompletionChunkKind (result->CompletionString, i);
+      cxstr = clang_getCompletionChunkText (result->CompletionString, i);
+      text = clang_getCString (cxstr);
+
+      if (text)
+        escaped = g_markup_escape_text (text, -1);
+      else
+        escaped = g_strdup ("");
+
+      switch (kind)
+        {
+        case CXCompletionChunk_Optional:
+          break;
+
+        case CXCompletionChunk_TypedText:
+          g_string_append_printf (markup, "<b>%s</b>", escaped);
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, text);
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          break;
+
+        case CXCompletionChunk_Text:
+          g_string_append (markup, escaped);
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, text);
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          break;
+
+        case CXCompletionChunk_Placeholder:
+          g_string_append (markup, escaped);
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, text);
+          ide_source_snippet_chunk_set_tab_stop (chunk, tab_stop++);
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          break;
+
+        case CXCompletionChunk_Informative:
+          if (0 == g_strcmp0 (text, "const "))
+            g_string_append (markup, text);
+          break;
+
+        case CXCompletionChunk_CurrentParameter:
+          break;
+
+        case CXCompletionChunk_LeftParen:
+          g_string_append (markup, " ");
+          /* fall through */
+        case CXCompletionChunk_RightParen:
+        case CXCompletionChunk_LeftBracket:
+        case CXCompletionChunk_RightBracket:
+        case CXCompletionChunk_LeftBrace:
+        case CXCompletionChunk_RightBrace:
+        case CXCompletionChunk_LeftAngle:
+        case CXCompletionChunk_RightAngle:
+        case CXCompletionChunk_Comma:
+        case CXCompletionChunk_Colon:
+        case CXCompletionChunk_SemiColon:
+        case CXCompletionChunk_Equal:
+        case CXCompletionChunk_HorizontalSpace:
+          g_string_append (markup, escaped);
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, text);
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          break;
+
+        case CXCompletionChunk_VerticalSpace:
+          g_string_append (markup, escaped);
+          /* insert the vertical space */
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, text);
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          /* now perform indentation */
+          chunk = ide_source_snippet_chunk_new ();
+          ide_source_snippet_chunk_set_text (chunk, "\t");
+          ide_source_snippet_add_chunk (snippet, chunk);
+          g_clear_object (&chunk);
+          break;
+
+        case CXCompletionChunk_ResultType:
+          g_string_append_printf (markup, "%s ", escaped);
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  self->snippet = g_object_ref (snippet);
+  self->markup = g_string_free (markup, FALSE);
+}
+
+static gchar *
+ide_clang_completion_item_get_markup (GtkSourceCompletionProposal *proposal)
+{
+  IdeClangCompletionItem *self = (IdeClangCompletionItem *)proposal;
+
+  g_assert (IDE_IS_CLANG_COMPLETION_ITEM (self));
+
+  ide_clang_completion_item_lazy_init (self);
+
+  return g_strdup (self->markup);
+}
+
+static GdkPixbuf *
+ide_clang_completion_item_get_icon (GtkSourceCompletionProposal *proposal)
+{
+  IdeClangCompletionItem *self = (IdeClangCompletionItem *)proposal;
+
+  g_assert (IDE_IS_CLANG_COMPLETION_ITEM (self));
+
+  ide_clang_completion_item_lazy_init (self);
+
+  return self->icon ? g_object_ref (self->icon) : NULL;
+}
 
 static void
 ide_clang_completion_item_finalize (GObject *object)
 {
   IdeClangCompletionItem *self = (IdeClangCompletionItem *)object;
 
+  g_clear_object (&self->icon);
+  g_clear_object (&self->snippet);
+  g_clear_pointer (&self->markup, g_free);
   g_clear_pointer (&self->results, ide_ref_ptr_unref);
 
   G_OBJECT_CLASS (ide_clang_completion_item_parent_class)->finalize (object);
 }
 
 static void
+ide_clang_completion_item_get_property (GObject    *object,
+                                        guint       prop_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+  IdeClangCompletionItem *self = IDE_CLANG_COMPLETION_ITEM (object);
+
+  switch (prop_id)
+    {
+    case PROP_INDEX:
+      g_value_set_uint (value, self->index);
+      break;
+
+    case PROP_RESULTS:
+      g_value_set_boxed (value, self->results);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
 ide_clang_completion_item_set_property (GObject      *object,
                                         guint         prop_id,
                                         const GValue *value,
@@ -86,144 +289,163 @@ ide_clang_completion_item_set_property (GObject      *object,
 }
 
 static void
+completion_proposal_iface_init (GtkSourceCompletionProposalIface *iface)
+{
+  iface->get_icon = ide_clang_completion_item_get_icon;
+  iface->get_markup = ide_clang_completion_item_get_markup;
+}
+
+static void
 ide_clang_completion_item_class_init (IdeClangCompletionItemClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->finalize = ide_clang_completion_item_finalize;
+  object_class->get_property = ide_clang_completion_item_get_property;
   object_class->set_property = ide_clang_completion_item_set_property;
 
   gParamSpecs [PROP_INDEX] =
     g_param_spec_uint ("index",
-                       "Index",
-                       "The index in the result structure.",
-                       0,
-                       G_MAXUINT,
-                       0,
-                       (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+                         _("Index"),
+                         _("The index in the result set."),
+                         0,
+                         G_MAXUINT-1,
+                         0,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, PROP_INDEX, gParamSpecs [PROP_INDEX]);
 
   gParamSpecs [PROP_RESULTS] =
     g_param_spec_boxed ("results",
-                        "Results",
-                        "The result set from clang.",
-                        IDE_TYPE_REF_PTR,
-                        (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+                         _("Results"),
+                         _("The clang result set."),
+                         IDE_TYPE_REF_PTR,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (object_class, PROP_RESULTS, gParamSpecs [PROP_RESULTS]);
 }
 
 static void
-ide_clang_completion_item_init (IdeClangCompletionItem *item)
+ide_clang_completion_item_init (IdeClangCompletionItem *self)
 {
+  self->typed_text_index = -1;
 }
 
-static CXCompletionResult *
-get_completion_result (GtkSourceCompletionProposal *proposal)
+/**
+ * ide_clang_completion_item_get_snippet:
+ * @self: A #IdeClangCompletionItem.
+ *
+ * Gets the #IdeSourceSnippet to be inserted when expanding this completion item.
+ *
+ * Returns: (transfer none): An #IdeSourceSnippet.
+ */
+IdeSourceSnippet *
+ide_clang_completion_item_get_snippet (IdeClangCompletionItem *self)
 {
-  IdeClangCompletionItem *self = (IdeClangCompletionItem *)proposal;
-  CXCodeCompleteResults *results;
-  CXCompletionResult *result;
-
-  results = ide_ref_ptr_get (self->results);
-  result = &results->Results [self->index];
+  g_return_val_if_fail (IDE_IS_CLANG_COMPLETION_ITEM (self), NULL);
 
-  return result;
+  return self->snippet;
 }
 
-static gchar *
-ide_clang_completion_item_get_label (GtkSourceCompletionProposal *proposal)
+/**
+ * ide_clang_completion_item_get_priority:
+ * @self: A #IdeClangCompletionItem.
+ *
+ * Gets the completion priority for sorting within the results.
+ *
+ * Returns: An unsigned integer.
+ */
+guint
+ide_clang_completion_item_get_priority (IdeClangCompletionItem *self)
 {
-  CXCompletionResult *result = get_completion_result (proposal);
-  GString *str;
-  unsigned num_chunks;
-  unsigned i;
-
-  str = g_string_new (NULL);
-  num_chunks = clang_getNumCompletionChunks (result->CompletionString);
-
-  for (i = 0; i < num_chunks; i++)
-    {
-      CXString cxstr;
+  CXCompletionResult *result;
 
-      cxstr = clang_getCompletionChunkText (result->CompletionString, i);
+  g_return_val_if_fail (IDE_IS_CLANG_COMPLETION_ITEM (self), 0);
 
-      if (str->len)
-        g_string_append_printf (str, " %s", clang_getCString (cxstr));
-      else
-        g_string_append (str, clang_getCString (cxstr));
-    }
+  result = ide_clang_completion_item_get_result (self);
 
-  return g_string_free (str, FALSE);
+  return clang_getCompletionPriority (result);
 }
 
-static void
-completion_proposal_iface_init (GtkSourceCompletionProposalIface *iface)
+/**
+ * ide_clang_completion_item_get_typed_text:
+ * @self: An #IdeClangCompletionItem.
+ *
+ * Gets the text that would be expected to be typed to insert this completion
+ * item into the text editor.
+ *
+ * Returns: A string which should not be modified or freed.
+ */
+const gchar *
+ide_clang_completion_item_get_typed_text (IdeClangCompletionItem *self)
 {
-  iface->get_label = ide_clang_completion_item_get_label;
-}
+  CXCompletionResult *result;
+  CXString cxstr;
 
-gint
-ide_clang_completion_item_sort (gconstpointer a,
-                                gconstpointer b)
-{
-  CXCompletionResult *ar = get_completion_result ((gpointer)a);
-  CXCompletionResult *br = get_completion_result ((gpointer)b);
-  unsigned aprio;
-  unsigned bprio;
+  g_return_val_if_fail (IDE_IS_CLANG_COMPLETION_ITEM (self), NULL);
 
-  aprio = clang_getCompletionPriority (ar->CompletionString);
-  bprio = clang_getCompletionPriority (br->CompletionString);
+  result = ide_clang_completion_item_get_result (self);
 
-  /* TODO: check that this is safe */
+  /*
+   * Determine the index of the typed text. Each completion result should have
+   * exaction one of these.
+   */
+  if (self->typed_text_index == -1)
+    {
+      guint num_chunks;
+      guint i;
 
-  return (gint)aprio - (gint)bprio;
-}
+      num_chunks = clang_getNumCompletionChunks (result);
 
-gboolean
-ide_clang_completion_item_matches (IdeClangCompletionItem *self,
-                                   const gchar            *text)
-{
-  CXCompletionResult *result = get_completion_result ((GtkSourceCompletionProposal *)self);
-  enum CXAvailabilityKind availability;
-  unsigned chunks;
-  unsigned i;
-
-  g_return_val_if_fail (IDE_IS_CLANG_COMPLETION_ITEM (self), text);
+      for (i = 0; i < num_chunks; i++)
+        {
+          enum CXCompletionChunkKind kind;
 
-  availability = clang_getCompletionAvailability (result->CompletionString);
+          kind = clang_getCompletionChunkKind (result->CompletionString, i);
+          if (kind == CXCompletionChunk_TypedText)
+            {
+              self->typed_text_index = i;
+              break;
+            }
+        }
+    }
 
-  switch (availability)
-    {
-    case CXAvailability_NotAvailable:
-    case CXAvailability_NotAccessible:
-      return FALSE;
+#ifndef IDE_DISABLE_TRACE
+  {
+    enum CXCompletionChunkKind kind;
+    unsigned num_chunks;
 
-    default:
-      break;
-    }
+    g_assert_cmpint (self->typed_text_index, >=, 0);
 
-  chunks = clang_getNumCompletionChunks (result->CompletionString);
+    num_chunks = clang_getNumCompletionChunks (result->CompletionString);
+    g_assert_cmpint (num_chunks, >, self->typed_text_index);
 
-  for (i = 0; i < chunks; i++)
-    {
-      enum CXCompletionChunkKind kind;
+    kind = clang_getCompletionChunkKind (result->CompletionString, self->typed_text_index);
+    g_assert_cmpint (kind, ==, CXCompletionChunk_TypedText);
+  }
+#endif
 
-      kind = clang_getCompletionChunkKind (result->CompletionString, i);
+  cxstr = clang_getCompletionChunkText (result->CompletionString, self->typed_text_index);
 
-      if (kind == CXCompletionChunk_TypedText)
-        {
-          CXString cxstr;
+  return clang_getCString (cxstr);
+}
 
-          cxstr = clang_getCompletionChunkText(result->CompletionString, i);
-          if (g_str_has_prefix (clang_getCString (cxstr), text))
-            {
-              clang_disposeString (cxstr);
-              return TRUE;
-            }
+/**
+ * ide_clang_completion_item_get_brief_comment:
+ * @self: An #IdeClangCompletionItem.
+ *
+ * Gets the brief comment that can be used to show extra information for the
+ * result.
+ *
+ * Returns: A string which should not be modified or freed.
+ */
+const gchar *
+ide_clang_completion_item_get_brief_comment (IdeClangCompletionItem *self)
+{
+  CXCompletionResult *result;
+  CXString cxstr;
 
-          clang_disposeString (cxstr);
-        }
-    }
+  g_return_val_if_fail (IDE_IS_CLANG_COMPLETION_ITEM (self), NULL);
 
-  return FALSE;
+  result = ide_clang_completion_item_get_result (self);
+  cxstr = clang_getCompletionBriefComment (result->CompletionString);
+  return clang_getCString (cxstr);
 }
diff --git a/libide/clang/ide-clang-completion-item.h b/libide/clang/ide-clang-completion-item.h
index 60d458d..2299fe5 100644
--- a/libide/clang/ide-clang-completion-item.h
+++ b/libide/clang/ide-clang-completion-item.h
@@ -19,7 +19,9 @@
 #ifndef IDE_CLANG_COMPLETION_ITEM_H
 #define IDE_CLANG_COMPLETION_ITEM_H
 
-#include <glib-object.h>
+#include <gtksourceview/gtksourcecompletionproposal.h>
+
+#include "ide-source-snippet.h"
 
 G_BEGIN_DECLS
 
@@ -31,14 +33,14 @@ G_BEGIN_DECLS
 #define IDE_IS_CLANG_COMPLETION_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
IDE_TYPE_CLANG_COMPLETION_ITEM))
 #define IDE_CLANG_COMPLETION_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
IDE_TYPE_CLANG_COMPLETION_ITEM, IdeClangCompletionItemClass))
 
-typedef struct _IdeClangCompletionItem        IdeClangCompletionItem;
-typedef struct _IdeClangCompletionItemClass   IdeClangCompletionItemClass;
+typedef struct _IdeClangCompletionItem      IdeClangCompletionItem;
+typedef struct _IdeClangCompletionItemClass IdeClangCompletionItemClass;
 
-GType    ide_clang_completion_item_get_type (void);
-gboolean ide_clang_completion_item_matches  (IdeClangCompletionItem *self,
-                                             const gchar            *text);
-gint     ide_clang_completion_item_sort     (gconstpointer           a,
-                                             gconstpointer           b);
+GType             ide_clang_completion_item_get_type          (void);
+IdeSourceSnippet *ide_clang_completion_item_get_snippet       (IdeClangCompletionItem *self);
+const gchar      *ide_clang_completion_item_get_typed_text    (IdeClangCompletionItem *self);
+guint             ide_clang_completion_item_get_priority      (IdeClangCompletionItem *self);
+const gchar      *ide_clang_completion_item_get_brief_comment (IdeClangCompletionItem *self);
 
 G_END_DECLS
 
diff --git a/libide/clang/ide-clang-completion-provider.c b/libide/clang/ide-clang-completion-provider.c
index 2d8ff77..4a5f7d0 100644
--- a/libide/clang/ide-clang-completion-provider.c
+++ b/libide/clang/ide-clang-completion-provider.c
@@ -28,6 +28,8 @@
 #include "ide-context.h"
 #include "ide-debug.h"
 #include "ide-file.h"
+#include "ide-source-snippet.h"
+#include "ide-source-view.h"
 
 struct _IdeClangCompletionProviderClass
 {
@@ -38,7 +40,8 @@ struct _IdeClangCompletionProvider
 {
   GObject parent_instance;
 
-  GPtrArray *last_results;
+  IdeSourceView *view;
+  GPtrArray     *last_results;
 };
 
 typedef struct
@@ -101,6 +104,16 @@ stop_on_predicate (gunichar ch,
     }
 }
 
+static gboolean
+matches (IdeClangCompletionItem *item,
+         const gchar            *word)
+{
+  const gchar *typed_text;
+
+  typed_text = ide_clang_completion_item_get_typed_text (item);
+  return !!strstr (typed_text, word);
+}
+
 static gchar *
 get_word (const GtkTextIter *location)
 {
@@ -134,7 +147,7 @@ filter_list (GPtrArray   *ar,
       IdeClangCompletionItem *item;
 
       item = g_ptr_array_index (ar, i);
-      if (ide_clang_completion_item_matches (item, word))
+      if (matches (item, word))
         g_ptr_array_add (matched, item);
     }
 
@@ -252,22 +265,35 @@ static void
 ide_clang_completion_provider_populate (GtkSourceCompletionProvider *provider,
                                         GtkSourceCompletionContext  *context)
 {
+  IdeClangCompletionProvider *self = (IdeClangCompletionProvider *)provider;
   AddProposalsState *state;
   IdeClangService *service;
+  GtkSourceCompletion *completion;
+  GtkSourceView *view;
   GtkTextBuffer *buffer;
   IdeContext *icontext;
   GtkTextIter iter;
   IdeFile *file;
 
+  g_assert (IDE_IS_CLANG_COMPLETION_PROVIDER (self));
+
   if (!gtk_source_completion_context_get_iter (context, &iter))
     goto failure;
 
   buffer = gtk_text_iter_get_buffer (&iter);
   if (buffer == NULL)
     goto failure;
-
   g_assert (IDE_IS_BUFFER (buffer));
 
+  /* stash the view for later */
+  g_object_get (context, "completion", &completion, NULL);
+  g_assert (GTK_SOURCE_IS_COMPLETION (completion));
+  view = gtk_source_completion_get_view (completion);
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+  g_assert ((self->view == NULL) || (self->view == (IdeSourceView *)view));
+  self->view = IDE_SOURCE_VIEW (view);
+  g_clear_object (&completion);
+
   file = ide_buffer_get_file (IDE_BUFFER (buffer));
   if (file == NULL)
     goto failure;
@@ -321,7 +347,24 @@ ide_clang_completion_provider_activate_proposal (GtkSourceCompletionProvider *pr
                                                  GtkSourceCompletionProposal *proposal,
                                                  GtkTextIter                 *iter)
 {
-  return FALSE;
+  IdeClangCompletionProvider *self = (IdeClangCompletionProvider *)provider;
+  IdeClangCompletionItem *item = (IdeClangCompletionItem *)proposal;
+  IdeSourceSnippet *snippet;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_CLANG_COMPLETION_PROVIDER (self));
+  g_assert (IDE_IS_CLANG_COMPLETION_ITEM (item));
+
+  snippet = ide_clang_completion_item_get_snippet (item);
+
+  g_assert (snippet != NULL);
+  g_assert (IDE_IS_SOURCE_SNIPPET (snippet));
+  g_assert (IDE_IS_SOURCE_VIEW (self->view));
+
+  ide_source_view_push_snippet (self->view, snippet);
+
+  IDE_RETURN (TRUE);
 }
 
 static gint


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