[gnome-builder: 35/139] libide-sourceview: add libide-sourceview static library



commit 3f1034e3089303297d3ba0f35a5da95cfb73ac89
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jan 9 16:14:32 2019 -0800

    libide-sourceview: add libide-sourceview static library
    
    This refactors the sourceview components into a new static library that
    can be used to build upon the libide-code library. It will be used by
    the editor library to build the editor components.

 src/libide/completion/meson.build                  |   42 -
 src/libide/hover/meson.build                       |   22 -
 src/libide/snippets/meson.build                    |   25 -
 src/libide/sourceview/gtk/menus.ui                 |  117 ++
 .../ide-completion-context.c                       |   12 +-
 .../ide-completion-context.h                       |    8 +-
 .../ide-completion-display.c                       |    8 +-
 .../ide-completion-display.h                       |    8 +-
 .../ide-completion-list-box-row.c                  |    2 +-
 .../ide-completion-list-box-row.h                  |    5 +-
 .../ide-completion-list-box-row.ui                 |    0
 .../ide-completion-list-box.c                      |    0
 .../ide-completion-list-box.h                      |   16 +-
 .../ide-completion-overlay.c                       |    4 +-
 .../ide-completion-overlay.h                       |    9 +-
 .../ide-completion-overlay.ui                      |    0
 .../ide-completion-private.h                       |   10 +-
 .../ide-completion-proposal.c                      |    0
 .../ide-completion-proposal.h                      |    6 +-
 .../ide-completion-provider.c                      |   10 +-
 .../ide-completion-provider.h                      |    9 +-
 .../ide-completion-types.h                         |   12 +-
 .../ide-completion-view.c                          |   18 +-
 .../ide-completion-view.h                          |   11 +-
 .../ide-completion-view.ui                         |    0
 .../ide-completion-window.c                        |   42 +-
 .../ide-completion-window.h                        |   10 +-
 .../ide-completion-window.ui                       |    0
 .../{completion => sourceview}/ide-completion.c    |   49 +-
 .../{completion => sourceview}/ide-completion.h    |   11 +-
 src/libide/sourceview/ide-cursor.c                 |    6 +-
 src/libide/sourceview/ide-gutter.c                 |  128 ++
 src/libide/sourceview/ide-gutter.h                 |   58 +
 .../ide-hover-context-private.h                    |    6 +-
 .../{hover => sourceview}/ide-hover-context.c      |    9 +-
 .../{hover => sourceview}/ide-hover-context.h      |   11 +-
 .../ide-hover-popover-private.h                    |    0
 .../{hover => sourceview}/ide-hover-popover.c      |    9 +-
 .../{hover => sourceview}/ide-hover-private.h      |    4 +-
 .../{hover => sourceview}/ide-hover-provider.c     |    6 +-
 .../{hover => sourceview}/ide-hover-provider.h     |   10 +-
 src/libide/{hover => sourceview}/ide-hover.c       |   42 +-
 src/libide/sourceview/ide-indenter.c               |    5 +-
 src/libide/sourceview/ide-indenter.h               |    9 +-
 src/libide/sourceview/ide-language.c               |  109 --
 src/libide/sourceview/ide-language.h               |   33 -
 .../sourceview/ide-line-change-gutter-renderer.c   |  466 +++---
 .../sourceview/ide-line-change-gutter-renderer.h   |    5 +-
 src/libide/sourceview/ide-omni-gutter-renderer.c   | 1700 --------------------
 src/libide/sourceview/ide-omni-gutter-renderer.h   |   42 -
 .../{snippets => sourceview}/ide-snippet-chunk.c   |    0
 .../{snippets => sourceview}/ide-snippet-chunk.h   |    8 +-
 .../{snippets => sourceview}/ide-snippet-context.c |    0
 .../{snippets => sourceview}/ide-snippet-context.h |    6 +-
 .../{snippets => sourceview}/ide-snippet-parser.c  |   10 +-
 .../{snippets => sourceview}/ide-snippet-parser.h  |    4 +
 .../{snippets => sourceview}/ide-snippet-private.h |    0
 .../{snippets => sourceview}/ide-snippet-storage.c |   63 +-
 .../{snippets => sourceview}/ide-snippet-storage.h |   22 +-
 ...tter-renderer-private.h => ide-snippet-types.h} |   14 +-
 src/libide/{snippets => sourceview}/ide-snippet.c  |   13 +-
 src/libide/{snippets => sourceview}/ide-snippet.h  |    6 +-
 src/libide/sourceview/ide-source-search-context.c  |    5 +-
 src/libide/sourceview/ide-source-search-context.h  |    7 +-
 src/libide/sourceview/ide-source-view-capture.c    |    3 +-
 src/libide/sourceview/ide-source-view-capture.h    |    7 +-
 src/libide/sourceview/ide-source-view-mode.c       |    7 +-
 src/libide/sourceview/ide-source-view-mode.h       |    8 +-
 src/libide/sourceview/ide-source-view-movements.c  |   76 +-
 src/libide/sourceview/ide-source-view-movements.h  |    4 +-
 src/libide/sourceview/ide-source-view-private.h    |   10 +-
 src/libide/sourceview/ide-source-view-shortcuts.c  |   13 +-
 src/libide/sourceview/ide-source-view.c            |  622 ++++---
 src/libide/sourceview/ide-source-view.h            |   56 +-
 .../sourceview/libide-sourceview.gresource.xml     |   12 +
 src/libide/sourceview/libide-sourceview.h          |   53 +
 src/libide/sourceview/meson.build                  |  182 ++-
 77 files changed, 1419 insertions(+), 2916 deletions(-)
---
diff --git a/src/libide/sourceview/gtk/menus.ui b/src/libide/sourceview/gtk/menus.ui
new file mode 100644
index 000000000..2af02abd7
--- /dev/null
+++ b/src/libide/sourceview/gtk/menus.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <menu id="ide-source-view-popup-menu">
+    <section id="ide-source-view-popup-menu-jump-section">
+      <item>
+        <attribute name="label" translatable="yes">_Go to Definition</attribute>
+        <attribute name="action">sourceview.goto-definition</attribute>
+      </item>
+    </section>
+    <section id="ide-source-view-popup-menu-undo-section">
+      <item>
+        <attribute name="label" translatable="yes">_Undo</attribute>
+        <attribute name="action">sourceview.undo</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Redo</attribute>
+        <attribute name="action">sourceview.redo</attribute>
+      </item>
+    </section>
+    <section id="ide-source-view-popup-menu-clipboard-section">
+      <item>
+        <attribute name="label" translatable="yes">C_ut</attribute>
+        <attribute name="action">sourceview.cut-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="id">copy</attribute>
+        <attribute name="label" translatable="yes">_Copy</attribute>
+        <attribute name="action">sourceview.copy-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Paste</attribute>
+        <attribute name="action">sourceview.paste-clipboard</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Delete</attribute>
+        <attribute name="action">sourceview.delete-selection</attribute>
+      </item>
+    </section>
+    <section id="ide-source-view-popup-menu-spellcheck-section">
+    </section>
+    <section id="ide-source-view-popup-menu-highlighting-section">
+      <submenu id="ide-source-view-popup-menu-highlighting-submenu">
+        <attribute name="label" translatable="yes">Highlighting</attribute>
+      </submenu>
+    </section>
+    <section id="ide-source-view-popup-menu-selection-section">
+      <submenu id="ide-source-view-popup-menu-selection-submenu">
+        <attribute name="label" translatable="yes">Selection</attribute>
+        <item>
+          <attribute name="label" translatable="yes">Select _All</attribute>
+          <attribute name="action">sourceview.select-all</attribute>
+          <attribute name="target" type="(b)">(true,)</attribute>
+        </item>
+        <item>
+          <attribute name="label" translatable="yes">Select _None</attribute>
+          <attribute name="action">sourceview.select-all</attribute>
+          <attribute name="target" type="(b)">(false,)</attribute>
+        </item>
+        <section id="ide-source-view-popup-menu-case-section">
+          <item>
+            <attribute name="label" translatable="yes">All _Upper Case</attribute>
+            <attribute name="action">sourceview.change-case</attribute>
+            <attribute name="target" type="(u)">(1,)</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">All _Lower Case</attribute>
+            <attribute name="action">sourceview.change-case</attribute>
+            <attribute name="target" type="(u)">(0,)</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">_Invert Case</attribute>
+            <attribute name="action">sourceview.change-case</attribute>
+            <attribute name="target" type="(u)">(2,)</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">_Title Case</attribute>
+            <attribute name="action">sourceview.change-case</attribute>
+            <attribute name="target" type="(u)">(3,)</attribute>
+          </item>
+        </section>
+        <section id="ide-source-view-popup-menu-line-section">
+          <item>
+            <attribute name="label" translatable="yes">Join Lines</attribute>
+            <attribute name="action">sourceview.join-lines</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Sort Lines</attribute>
+            <attribute name="action">sourceview.sort</attribute>
+            <attribute name="target" type="(bb)">(false,false)</attribute>
+          </item>
+        </section>
+      </submenu>
+    </section>
+    <section id="ide-source-view-popup-menu-zoom-section">
+      <submenu id="ide-source-view-popup-menu-zoom-section-submenu">
+        <attribute name="label" translatable="yes">Zoom</attribute>
+        <item>
+          <attribute name="label" translatable="yes">Zoom _In</attribute>
+          <attribute name="action">sourceview.increase-font-size</attribute>
+          <attribute name="accel">&lt;control&gt;plus</attribute>
+        </item>
+        <item>
+          <attribute name="label" translatable="yes">Zoom _Out</attribute>
+          <attribute name="action">sourceview.decrease-font-size</attribute>
+            <attribute name="accel">&lt;control&gt;minus</attribute>
+        </item>
+        <section id="ide-source-view-popup-menu-zoom-section-submenu-reset">
+          <item>
+            <attribute name="label" translatable="yes">Reset</attribute>
+            <attribute name="action">sourceview.reset-font-size</attribute>
+            <attribute name="accel">&lt;control&gt;0</attribute>
+          </item>
+        </section>
+      </submenu>
+    </section>
+  </menu>
+</interface>
diff --git a/src/libide/completion/ide-completion-context.c b/src/libide/sourceview/ide-completion-context.c
similarity index 99%
rename from src/libide/completion/ide-completion-context.c
rename to src/libide/sourceview/ide-completion-context.c
index 64ab53b48..6fdbb117a 100644
--- a/src/libide/completion/ide-completion-context.c
+++ b/src/libide/sourceview/ide-completion-context.c
@@ -23,14 +23,14 @@
 #include "config.h"
 
 #include <dazzle.h>
+#include <libide-threading.h>
 #include <string.h>
 
-#include "completion/ide-completion.h"
-#include "completion/ide-completion-context.h"
-#include "completion/ide-completion-private.h"
-#include "completion/ide-completion-proposal.h"
-#include "completion/ide-completion-provider.h"
-#include "threading/ide-task.h"
+#include "ide-completion.h"
+#include "ide-completion-context.h"
+#include "ide-completion-private.h"
+#include "ide-completion-proposal.h"
+#include "ide-completion-provider.h"
 
 struct _IdeCompletionContext
 {
diff --git a/src/libide/completion/ide-completion-context.h b/src/libide/sourceview/ide-completion-context.h
similarity index 95%
rename from src/libide/completion/ide-completion-context.h
rename to src/libide/sourceview/ide-completion-context.h
index 6a82a951a..40110c192 100644
--- a/src/libide/completion/ide-completion-context.h
+++ b/src/libide/sourceview/ide-completion-context.h
@@ -20,11 +20,13 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <gtk/gtk.h>
 
-#include "completion/ide-completion-types.h"
+#include "ide-completion-types.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/completion/ide-completion-display.c b/src/libide/sourceview/ide-completion-display.c
similarity index 94%
rename from src/libide/completion/ide-completion-display.c
rename to src/libide/sourceview/ide-completion-display.c
index b429f6956..946909d22 100644
--- a/src/libide/completion/ide-completion-display.c
+++ b/src/libide/sourceview/ide-completion-display.c
@@ -22,10 +22,10 @@
 
 #include "config.h"
 
-#include "completion/ide-completion-context.h"
-#include "completion/ide-completion-display.h"
-#include "completion/ide-completion-private.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-completion-context.h"
+#include "ide-completion-display.h"
+#include "ide-completion-private.h"
+#include "ide-source-view.h"
 
 G_DEFINE_INTERFACE (IdeCompletionDisplay, ide_completion_display, GTK_TYPE_WIDGET)
 
diff --git a/src/libide/completion/ide-completion-display.h b/src/libide/sourceview/ide-completion-display.h
similarity index 94%
rename from src/libide/completion/ide-completion-display.h
rename to src/libide/sourceview/ide-completion-display.h
index 641121f23..80da7a893 100644
--- a/src/libide/completion/ide-completion-display.h
+++ b/src/libide/sourceview/ide-completion-display.h
@@ -20,11 +20,13 @@
 
 #pragma once
 
-#include <gtksourceview/gtksource.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <gtksourceview/gtksource.h>
 
-#include "completion/ide-completion-types.h"
+#include "ide-completion-types.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/completion/ide-completion-list-box-row.c 
b/src/libide/sourceview/ide-completion-list-box-row.c
similarity index 99%
rename from src/libide/completion/ide-completion-list-box-row.c
rename to src/libide/sourceview/ide-completion-list-box-row.c
index 828b444b1..31b4fd7fa 100644
--- a/src/libide/completion/ide-completion-list-box-row.c
+++ b/src/libide/sourceview/ide-completion-list-box-row.c
@@ -122,7 +122,7 @@ ide_completion_list_box_row_class_init (IdeCompletionListBoxRowClass *klass)
 
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
-  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-completion-list-box-row.ui");
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-sourceview/ui/ide-completion-list-box-row.ui");
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionListBoxRow, box);
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionListBoxRow, image);
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionListBoxRow, left);
diff --git a/src/libide/completion/ide-completion-list-box-row.h 
b/src/libide/sourceview/ide-completion-list-box-row.h
similarity index 95%
rename from src/libide/completion/ide-completion-list-box-row.h
rename to src/libide/sourceview/ide-completion-list-box-row.h
index f7c066ba0..b945df155 100644
--- a/src/libide/completion/ide-completion-list-box-row.h
+++ b/src/libide/sourceview/ide-completion-list-box-row.h
@@ -20,10 +20,13 @@
 
 #pragma once
 
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
 #include <gtk/gtk.h>
 
 #include "ide-completion-proposal.h"
-#include "ide-version-macros.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/completion/ide-completion-list-box-row.ui 
b/src/libide/sourceview/ide-completion-list-box-row.ui
similarity index 100%
rename from src/libide/completion/ide-completion-list-box-row.ui
rename to src/libide/sourceview/ide-completion-list-box-row.ui
diff --git a/src/libide/completion/ide-completion-list-box.c b/src/libide/sourceview/ide-completion-list-box.c
similarity index 100%
rename from src/libide/completion/ide-completion-list-box.c
rename to src/libide/sourceview/ide-completion-list-box.c
diff --git a/src/libide/completion/ide-completion-list-box.h b/src/libide/sourceview/ide-completion-list-box.h
similarity index 91%
rename from src/libide/completion/ide-completion-list-box.h
rename to src/libide/sourceview/ide-completion-list-box.h
index f521e85b0..193ffa806 100644
--- a/src/libide/completion/ide-completion-list-box.h
+++ b/src/libide/sourceview/ide-completion-list-box.h
@@ -20,39 +20,35 @@
 
 #pragma once
 
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
 #include <dazzle.h>
 #include <gtk/gtk.h>
 
 #include "ide-completion-context.h"
 #include "ide-completion-proposal.h"
-#include "ide-version-macros.h"
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_COMPLETION_LIST_BOX (ide_completion_list_box_get_type())
 
-IDE_AVAILABLE_IN_3_32
+
 G_DECLARE_FINAL_TYPE (IdeCompletionListBox, ide_completion_list_box, IDE, COMPLETION_LIST_BOX, DzlBin)
 
-IDE_AVAILABLE_IN_3_32
+
 GtkWidget             *ide_completion_list_box_new          (void);
-IDE_AVAILABLE_IN_3_32
 IdeCompletionContext  *ide_completion_list_box_get_context  (IdeCompletionListBox   *self);
-IDE_AVAILABLE_IN_3_32
 void                   ide_completion_list_box_set_context  (IdeCompletionListBox   *self,
                                                              IdeCompletionContext   *context);
-IDE_AVAILABLE_IN_3_32
 guint                  ide_completion_list_box_get_n_rows   (IdeCompletionListBox   *self);
-IDE_AVAILABLE_IN_3_32
 void                   ide_completion_list_box_set_n_rows   (IdeCompletionListBox   *self,
                                                              guint                   n_rows);
-IDE_AVAILABLE_IN_3_32
 IdeCompletionProposal *ide_completion_list_box_get_proposal (IdeCompletionListBox   *self);
-IDE_AVAILABLE_IN_3_32
 gboolean               ide_completion_list_box_get_selected (IdeCompletionListBox   *self,
                                                              IdeCompletionProvider **provider,
                                                              IdeCompletionProposal **proposal);
-IDE_AVAILABLE_IN_3_32
 void                   ide_completion_list_box_move_cursor  (IdeCompletionListBox   *self,
                                                              GtkMovementStep         step,
                                                              gint                    direction);
diff --git a/src/libide/completion/ide-completion-overlay.c b/src/libide/sourceview/ide-completion-overlay.c
similarity index 99%
rename from src/libide/completion/ide-completion-overlay.c
rename to src/libide/sourceview/ide-completion-overlay.c
index 24ee39ea7..038737734 100644
--- a/src/libide/completion/ide-completion-overlay.c
+++ b/src/libide/sourceview/ide-completion-overlay.c
@@ -102,11 +102,11 @@ ide_completion_overlay_class_init (IdeCompletionOverlayClass *klass)
                          "The context to be displayed",
                          IDE_TYPE_COMPLETION_CONTEXT,
                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-  
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   gtk_widget_class_set_css_name (widget_class, "completionoverlay");
-  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-completion-overlay.ui");
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-sourceview/ui/ide-completion-overlay.ui");
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionOverlay, view);
 
   g_type_ensure (IDE_TYPE_COMPLETION_VIEW);
diff --git a/src/libide/completion/ide-completion-overlay.h b/src/libide/sourceview/ide-completion-overlay.h
similarity index 84%
rename from src/libide/completion/ide-completion-overlay.h
rename to src/libide/sourceview/ide-completion-overlay.h
index 872aea8cc..3c476ae9a 100644
--- a/src/libide/completion/ide-completion-overlay.h
+++ b/src/libide/sourceview/ide-completion-overlay.h
@@ -20,17 +20,18 @@
 
 #pragma once
 
-#include <dazzle.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <dazzle.h>
 
-#include "completion/ide-completion-context.h"
+#include "ide-completion-context.h"
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_COMPLETION_OVERLAY (ide_completion_overlay_get_type())
 
-IDE_AVAILABLE_IN_3_32
 G_DECLARE_FINAL_TYPE (IdeCompletionOverlay, ide_completion_overlay, IDE, COMPLETION_OVERLAY, DzlBin)
 
 G_END_DECLS
diff --git a/src/libide/completion/ide-completion-overlay.ui b/src/libide/sourceview/ide-completion-overlay.ui
similarity index 100%
rename from src/libide/completion/ide-completion-overlay.ui
rename to src/libide/sourceview/ide-completion-overlay.ui
diff --git a/src/libide/completion/ide-completion-private.h b/src/libide/sourceview/ide-completion-private.h
similarity index 95%
rename from src/libide/completion/ide-completion-private.h
rename to src/libide/sourceview/ide-completion-private.h
index 999a398ac..12b3761ad 100644
--- a/src/libide/completion/ide-completion-private.h
+++ b/src/libide/sourceview/ide-completion-private.h
@@ -20,11 +20,17 @@
 
 #pragma once
 
-#include "completion/ide-completion-types.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-completion-types.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
+typedef struct _IdeCompletionListBox    IdeCompletionListBox;
+typedef struct _IdeCompletionListBoxRow IdeCompletionListBoxRow;
+typedef struct _IdeCompletionOverlay    IdeCompletionOverlay;
+typedef struct _IdeCompletionView       IdeCompletionView;
+typedef struct _IdeCompletionWindow     IdeCompletionWindow;
+
 IdeCompletionWindow     *_ide_completion_window_new                (GtkWidget                   *view);
 void                     _ide_completion_view_set_font_desc        (IdeCompletionView           *self,
                                                                     const PangoFontDescription  *font_desc);
diff --git a/src/libide/completion/ide-completion-proposal.c b/src/libide/sourceview/ide-completion-proposal.c
similarity index 100%
rename from src/libide/completion/ide-completion-proposal.c
rename to src/libide/sourceview/ide-completion-proposal.c
diff --git a/src/libide/completion/ide-completion-proposal.h b/src/libide/sourceview/ide-completion-proposal.h
similarity index 86%
rename from src/libide/completion/ide-completion-proposal.h
rename to src/libide/sourceview/ide-completion-proposal.h
index 1875f7bc0..c687e94f4 100644
--- a/src/libide/completion/ide-completion-proposal.h
+++ b/src/libide/sourceview/ide-completion-proposal.h
@@ -20,9 +20,11 @@
 
 #pragma once
 
-#include <glib-object.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/completion/ide-completion-provider.c b/src/libide/sourceview/ide-completion-provider.c
similarity index 98%
rename from src/libide/completion/ide-completion-provider.c
rename to src/libide/sourceview/ide-completion-provider.c
index ab9b6b73e..918f1be0d 100644
--- a/src/libide/completion/ide-completion-provider.c
+++ b/src/libide/sourceview/ide-completion-provider.c
@@ -22,11 +22,11 @@
 
 #include "config.h"
 
-#include "completion/ide-completion-context.h"
-#include "completion/ide-completion-private.h"
-#include "completion/ide-completion-proposal.h"
-#include "completion/ide-completion-provider.h"
-#include "completion/ide-completion-list-box-row.h"
+#include "ide-completion-context.h"
+#include "ide-completion-private.h"
+#include "ide-completion-proposal.h"
+#include "ide-completion-provider.h"
+#include "ide-completion-list-box-row.h"
 
 G_DEFINE_INTERFACE (IdeCompletionProvider, ide_completion_provider, G_TYPE_OBJECT)
 
diff --git a/src/libide/completion/ide-completion-provider.h b/src/libide/sourceview/ide-completion-provider.h
similarity index 97%
rename from src/libide/completion/ide-completion-provider.h
rename to src/libide/sourceview/ide-completion-provider.h
index 6543730a5..8067f456f 100644
--- a/src/libide/completion/ide-completion-provider.h
+++ b/src/libide/sourceview/ide-completion-provider.h
@@ -20,12 +20,13 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-context.h"
-#include "ide-version-macros.h"
+#include <gtk/gtk.h>
 
-#include "completion/ide-completion-types.h"
+#include "ide-completion-types.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/completion/ide-completion-types.h b/src/libide/sourceview/ide-completion-types.h
similarity index 70%
rename from src/libide/completion/ide-completion-types.h
rename to src/libide/sourceview/ide-completion-types.h
index 1047c4522..14554ed39 100644
--- a/src/libide/completion/ide-completion-types.h
+++ b/src/libide/sourceview/ide-completion-types.h
@@ -20,10 +20,20 @@
 
 #pragma once
 
-#include "ide-types.h"
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
+typedef struct _IdeCompletion           IdeCompletion;
+typedef struct _IdeCompletionContext    IdeCompletionContext;
+typedef struct _IdeCompletionDisplay    IdeCompletionDisplay;
+typedef struct _IdeCompletionProposal   IdeCompletionProposal;
+typedef struct _IdeCompletionProvider   IdeCompletionProvider;
+
 typedef enum
 {
   IDE_COMPLETION_INTERACTIVE,
diff --git a/src/libide/completion/ide-completion-view.c b/src/libide/sourceview/ide-completion-view.c
similarity index 97%
rename from src/libide/completion/ide-completion-view.c
rename to src/libide/sourceview/ide-completion-view.c
index 4b1d01811..ec10b634a 100644
--- a/src/libide/completion/ide-completion-view.c
+++ b/src/libide/sourceview/ide-completion-view.c
@@ -22,13 +22,13 @@
 
 #include "config.h"
 
-#include "completion/ide-completion.h"
-#include "completion/ide-completion-context.h"
-#include "completion/ide-completion-list-box.h"
-#include "completion/ide-completion-private.h"
-#include "completion/ide-completion-proposal.h"
-#include "completion/ide-completion-provider.h"
-#include "completion/ide-completion-view.h"
+#include "ide-completion.h"
+#include "ide-completion-context.h"
+#include "ide-completion-list-box.h"
+#include "ide-completion-private.h"
+#include "ide-completion-proposal.h"
+#include "ide-completion-provider.h"
+#include "ide-completion-view.h"
 
 struct _IdeCompletionView
 {
@@ -205,7 +205,7 @@ ide_completion_view_class_init (IdeCompletionViewClass *klass)
                          "The selected proposal",
                          IDE_TYPE_COMPLETION_PROPOSAL,
                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-  
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   /**
@@ -267,7 +267,7 @@ ide_completion_view_class_init (IdeCompletionViewClass *klass)
   widget_class->activate_signal = signals [ACTIVATE];
 
   gtk_widget_class_set_css_name (widget_class, "completionview");
-  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-completion-view.ui");
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-sourceview/ui/ide-completion-view.ui");
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionView, details);
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionView, list_box);
   gtk_widget_class_bind_template_callback (widget_class, on_notify_proposal_cb);
diff --git a/src/libide/completion/ide-completion-view.h b/src/libide/sourceview/ide-completion-view.h
similarity index 87%
rename from src/libide/completion/ide-completion-view.h
rename to src/libide/sourceview/ide-completion-view.h
index 422a5f846..40ad652c0 100644
--- a/src/libide/completion/ide-completion-view.h
+++ b/src/libide/sourceview/ide-completion-view.h
@@ -20,22 +20,21 @@
 
 #pragma once
 
-#include <dazzle.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <dazzle.h>
 
-#include "completion/ide-completion-types.h"
+#include "ide-completion-types.h"
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_COMPLETION_VIEW (ide_completion_view_get_type())
 
-IDE_AVAILABLE_IN_3_32
 G_DECLARE_FINAL_TYPE (IdeCompletionView, ide_completion_view, IDE, COMPLETION_VIEW, DzlBin)
 
-IDE_AVAILABLE_IN_3_32
 IdeCompletionContext *ide_completion_view_get_context (IdeCompletionView    *self);
-IDE_AVAILABLE_IN_3_32
 void                  ide_completion_view_set_context (IdeCompletionView    *self,
                                                        IdeCompletionContext *context);
 
diff --git a/src/libide/completion/ide-completion-view.ui b/src/libide/sourceview/ide-completion-view.ui
similarity index 100%
rename from src/libide/completion/ide-completion-view.ui
rename to src/libide/sourceview/ide-completion-view.ui
diff --git a/src/libide/completion/ide-completion-window.c b/src/libide/sourceview/ide-completion-window.c
similarity index 89%
rename from src/libide/completion/ide-completion-window.c
rename to src/libide/sourceview/ide-completion-window.c
index f13f893e7..b4882dc5d 100644
--- a/src/libide/completion/ide-completion-window.c
+++ b/src/libide/sourceview/ide-completion-window.c
@@ -52,14 +52,6 @@ G_DEFINE_TYPE_WITH_CODE (IdeCompletionWindow, ide_completion_window, GTK_TYPE_WI
 
 static GParamSpec *properties [N_PROPS];
 
-static void (*MoveToRect) (GdkWindow          *window,
-                           const GdkRectangle *rect,
-                           GdkGravity          rect_anchor,
-                           GdkGravity          window_anchor,
-                           GdkAnchorHints      anchor_hints,
-                           gint                rect_anchor_dx,
-                           gint                rect_anchor_dy);
-
 static gboolean
 ide_completion_window_reposition (IdeCompletionWindow *self)
 {
@@ -125,13 +117,13 @@ ide_completion_window_reposition (IdeCompletionWindow *self)
 /* TODO: figure out where this comes from */
 #define EXTRA_SPACE 9
 
-  MoveToRect (window,
-              &rect,
-              GDK_GRAVITY_SOUTH_WEST,
-              GDK_GRAVITY_NORTH_WEST,
-              GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_RESIZE_X,
-              -x_offset + EXTRA_SPACE,
-              0);
+  gdk_window_move_to_rect (window,
+                           &rect,
+                           GDK_GRAVITY_SOUTH_WEST,
+                           GDK_GRAVITY_NORTH_WEST,
+                           GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_RESIZE_X,
+                           -x_offset + EXTRA_SPACE,
+                           0);
 
   return TRUE;
 }
@@ -228,27 +220,9 @@ ide_completion_window_class_init (IdeCompletionWindowClass *klass)
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   gtk_widget_class_set_css_name (widget_class, "completionwindow");
-  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-completion-window.ui");
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/libide-sourceview/ui/ide-completion-window.ui");
   gtk_widget_class_bind_template_child (widget_class, IdeCompletionWindow, view);
 
-#if GTK_CHECK_VERSION(3, 23, 0)
-  MoveToRect = gdk_window_move_to_rect;
-#else
-    {
-      /*
-       * HACK: We don't have access to GDK_PRIVATE_CALL() for obvious reasons.
-       *       However, we are likely to get this in gtk+ 3.24 which will mean
-       *       we can delete this crazy hack before our 3.30 release.
-       *
-       *       We call gdk_private__() to get the GdkPrivateVTable and know that
-       *       the offset of move_to_rect is at 12*sizeof(void*).
-       */
-      gpointer *vtable = gdk__private__ ();
-      MoveToRect = vtable[12];
-      g_assert (MoveToRect != NULL);
-    }
-#endif
-
   g_type_ensure (IDE_TYPE_COMPLETION_VIEW);
 }
 
diff --git a/src/libide/completion/ide-completion-window.h b/src/libide/sourceview/ide-completion-window.h
similarity index 88%
rename from src/libide/completion/ide-completion-window.h
rename to src/libide/sourceview/ide-completion-window.h
index d0d9edc71..c5f04d153 100644
--- a/src/libide/completion/ide-completion-window.h
+++ b/src/libide/sourceview/ide-completion-window.h
@@ -20,20 +20,20 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <gtk/gtk.h>
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_COMPLETION_WINDOW (ide_completion_window_get_type())
 
-IDE_AVAILABLE_IN_3_32
 G_DECLARE_FINAL_TYPE (IdeCompletionWindow, ide_completion_window, IDE, COMPLETION_WINDOW, GtkWindow)
 
-IDE_AVAILABLE_IN_3_32
 IdeCompletionContext *ide_completion_window_get_context (IdeCompletionWindow  *self);
-IDE_AVAILABLE_IN_3_32
 void                  ide_completion_window_set_context (IdeCompletionWindow  *self,
                                                          IdeCompletionContext *context);
 
diff --git a/src/libide/completion/ide-completion-window.ui b/src/libide/sourceview/ide-completion-window.ui
similarity index 100%
rename from src/libide/completion/ide-completion-window.ui
rename to src/libide/sourceview/ide-completion-window.ui
diff --git a/src/libide/completion/ide-completion.c b/src/libide/sourceview/ide-completion.c
similarity index 97%
rename from src/libide/completion/ide-completion.c
rename to src/libide/sourceview/ide-completion.c
index c8635bad9..5b9e5dce0 100644
--- a/src/libide/completion/ide-completion.c
+++ b/src/libide/sourceview/ide-completion.c
@@ -25,6 +25,8 @@
 #include <gtk/gtk.h>
 #include <dazzle.h>
 #include <gtksourceview/gtksource.h>
+#include <libide-code.h>
+#include <libide-plugins.h>
 #include <libpeas/peas.h>
 #include <string.h>
 
@@ -32,16 +34,13 @@
 # include <gdk/gdkwayland.h>
 #endif
 
-#include "ide-debug.h"
-
-#include "buffers/ide-buffer.h"
-#include "completion/ide-completion.h"
-#include "completion/ide-completion-context.h"
-#include "completion/ide-completion-display.h"
-#include "completion/ide-completion-overlay.h"
-#include "completion/ide-completion-private.h"
-#include "completion/ide-completion-proposal.h"
-#include "completion/ide-completion-provider.h"
+#include "ide-completion.h"
+#include "ide-completion-context.h"
+#include "ide-completion-display.h"
+#include "ide-completion-overlay.h"
+#include "ide-completion-private.h"
+#include "ide-completion-proposal.h"
+#include "ide-completion-provider.h"
 
 #define DEFAULT_N_ROWS 5
 
@@ -824,8 +823,7 @@ ide_completion_addins_extension_added_cb (IdeExtensionSetAdapter *adapter,
 
   if ((buffer = ide_completion_get_buffer (self)) && IDE_IS_BUFFER (buffer))
     {
-      /* TODO: Remove this when no longer necessary */
-      IdeContext *context = ide_buffer_get_context (IDE_BUFFER (buffer));
+      g_autoptr(IdeContext) context = ide_buffer_ref_context (IDE_BUFFER (buffer));
       _ide_completion_provider_load (provider, context);
     }
 
@@ -860,8 +858,8 @@ ide_completion_buffer_signals_bind_cb (IdeCompletion   *self,
                                        DzlSignalGroup  *group)
 {
   GtkSourceLanguage *language;
+  IdeObjectBox *box;
   const gchar *language_id = NULL;
-  IdeContext *context;
 
   IDE_ENTRY;
 
@@ -875,22 +873,21 @@ ide_completion_buffer_signals_bind_cb (IdeCompletion   *self,
   if ((language = gtk_source_buffer_get_language (buffer)))
     language_id = gtk_source_language_get_id (language);
 
-  context = ide_buffer_get_context (IDE_BUFFER (buffer));
-
-  self->addins = ide_extension_set_adapter_new (context,
+  box = ide_object_box_from_object (G_OBJECT (buffer));
+  self->addins = ide_extension_set_adapter_new (IDE_OBJECT (box),
                                                 peas_engine_get_default (),
                                                 IDE_TYPE_COMPLETION_PROVIDER,
                                                 "Completion-Provider-Languages",
                                                 language_id);
 
-  g_signal_connect (self->addins,
-                    "extension-added",
-                    G_CALLBACK (ide_completion_addins_extension_added_cb),
-                    self);
-  g_signal_connect (self->addins,
-                    "extension-removed",
-                    G_CALLBACK (ide_completion_addins_extension_removed_cb),
-                    self);
+  g_signal_connect_object (self->addins,
+                           "extension-added",
+                           G_CALLBACK (ide_completion_addins_extension_added_cb),
+                           self, 0);
+  g_signal_connect_object (self->addins,
+                           "extension-removed",
+                           G_CALLBACK (ide_completion_addins_extension_removed_cb),
+                           self, 0);
 
   ide_extension_set_adapter_foreach (self->addins,
                                      ide_completion_addins_extension_added_cb,
@@ -908,7 +905,7 @@ ide_completion_buffer_signals_unbind_cb (IdeCompletion   *self,
   g_assert (IDE_IS_COMPLETION (self));
   g_assert (DZL_IS_SIGNAL_GROUP (group));
 
-  g_clear_object (&self->addins);
+  ide_clear_and_destroy_object (&self->addins);
 
   IDE_EXIT;
 }
@@ -977,7 +974,7 @@ ide_completion_finalize (GObject *object)
   dzl_clear_source (&self->queued_update);
 
   g_clear_object (&self->cancellable);
-  g_clear_object (&self->addins);
+  ide_clear_and_destroy_object (&self->addins);
   g_clear_object (&self->buffer_signals);
   g_clear_object (&self->context_signals);
   g_clear_object (&self->view_signals);
diff --git a/src/libide/completion/ide-completion.h b/src/libide/sourceview/ide-completion.h
similarity index 93%
rename from src/libide/completion/ide-completion.h
rename to src/libide/sourceview/ide-completion.h
index f7d644159..585f9dd87 100644
--- a/src/libide/completion/ide-completion.h
+++ b/src/libide/sourceview/ide-completion.h
@@ -20,12 +20,15 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <libide-core.h>
+#include <gtk/gtk.h>
 
-#include "completion/ide-completion-types.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-completion-types.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/sourceview/ide-cursor.c b/src/libide/sourceview/ide-cursor.c
index 7e99a0778..faa7411ba 100644
--- a/src/libide/sourceview/ide-cursor.c
+++ b/src/libide/sourceview/ide-cursor.c
@@ -24,9 +24,9 @@
 
 #include <dazzle.h>
 
-#include "sourceview/ide-source-view.h"
-#include "sourceview/ide-cursor.h"
-#include "sourceview/ide-text-util.h"
+#include "ide-source-view.h"
+#include "ide-cursor.h"
+#include "ide-text-util.h"
 
 struct _IdeCursor
 {
diff --git a/src/libide/sourceview/ide-gutter.c b/src/libide/sourceview/ide-gutter.c
new file mode 100644
index 000000000..43529efef
--- /dev/null
+++ b/src/libide/sourceview/ide-gutter.c
@@ -0,0 +1,128 @@
+/* ide-gutter.c
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-gutter"
+
+#include "config.h"
+
+#include "ide-gutter.h"
+
+G_DEFINE_INTERFACE (IdeGutter, ide_gutter, G_TYPE_OBJECT)
+
+enum {
+  STYLE_CHANGED,
+  N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+ide_gutter_default_init (IdeGutterInterface *iface)
+{
+  g_object_interface_install_property (iface,
+                                       g_param_spec_boolean ("show-line-changes",
+                                                             "Show Line Changes",
+                                                             "If line changes should be displayed",
+                                                             FALSE,
+                                                             (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  g_object_interface_install_property (iface,
+                                       g_param_spec_boolean ("show-line-diagnostics",
+                                                             "Show Line Diagnostics",
+                                                             "If line diagnostics should be displayed",
+                                                             FALSE,
+                                                             (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  g_object_interface_install_property (iface,
+                                       g_param_spec_boolean ("show-line-numbers",
+                                                             "Show Line Numbers",
+                                                             "If line numbers should be displayed",
+                                                             FALSE,
+                                                             (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  signals [STYLE_CHANGED] =
+    g_signal_new ("style-changed",
+                  G_TYPE_FROM_INTERFACE (iface),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (IdeGutterInterface, style_changed),
+                  NULL,
+                  NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+void
+ide_gutter_style_changed (IdeGutter *self)
+{
+  g_return_if_fail (IDE_IS_GUTTER (self));
+
+  g_signal_emit (self, signals [STYLE_CHANGED], 0);
+}
+
+gboolean
+ide_gutter_get_show_line_changes (IdeGutter *self)
+{
+  gboolean ret;
+  g_object_get (self, "show-line-changes", &ret, NULL);
+  return ret;
+}
+
+gboolean
+ide_gutter_get_show_line_numbers (IdeGutter *self)
+{
+  gboolean ret;
+  g_object_get (self, "show-line-numbers", &ret, NULL);
+  return ret;
+}
+
+gboolean
+ide_gutter_get_show_line_diagnostics (IdeGutter *self)
+{
+  gboolean ret;
+  g_object_get (self, "show-line-diagnostics", &ret, NULL);
+  return ret;
+}
+
+void
+ide_gutter_set_show_line_changes (IdeGutter *self,
+                                  gboolean   show_line_changes)
+{
+  g_return_if_fail (IDE_IS_GUTTER (self));
+
+  g_object_set (self, "show-line-changes", show_line_changes, NULL);
+}
+
+void
+ide_gutter_set_show_line_numbers (IdeGutter *self,
+                                  gboolean   show_line_numbers)
+{
+  g_return_if_fail (IDE_IS_GUTTER (self));
+
+  g_object_set (self, "show-line-numbers", show_line_numbers, NULL);
+}
+
+void
+ide_gutter_set_show_line_diagnostics (IdeGutter *self,
+                                      gboolean   show_line_diagnostics)
+{
+  g_return_if_fail (IDE_IS_GUTTER (self));
+
+  g_object_set (self, "show-line-diagnostics", show_line_diagnostics, NULL);
+}
diff --git a/src/libide/sourceview/ide-gutter.h b/src/libide/sourceview/ide-gutter.h
new file mode 100644
index 000000000..79a8ef918
--- /dev/null
+++ b/src/libide/sourceview/ide-gutter.h
@@ -0,0 +1,58 @@
+/* ide-gutter.h
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtksourceview/gtksource.h>
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_GUTTER (ide_gutter_get_type())
+
+IDE_AVAILABLE_IN_3_32
+G_DECLARE_INTERFACE (IdeGutter, ide_gutter, IDE, GUTTER, GObject)
+
+struct _IdeGutterInterface
+{
+  GTypeInterface parent_class;
+
+  void (*style_changed) (IdeGutter *self);
+};
+
+IDE_AVAILABLE_IN_3_32
+gboolean ide_gutter_get_show_line_changes     (IdeGutter *self);
+IDE_AVAILABLE_IN_3_32
+gboolean ide_gutter_get_show_line_numbers     (IdeGutter *self);
+IDE_AVAILABLE_IN_3_32
+gboolean ide_gutter_get_show_line_diagnostics (IdeGutter *self);
+IDE_AVAILABLE_IN_3_32
+void     ide_gutter_set_show_line_changes     (IdeGutter *self,
+                                               gboolean   show_line_changes);
+IDE_AVAILABLE_IN_3_32
+void     ide_gutter_set_show_line_numbers     (IdeGutter *self,
+                                               gboolean   show_line_numbers);
+IDE_AVAILABLE_IN_3_32
+void     ide_gutter_set_show_line_diagnostics (IdeGutter *self,
+                                               gboolean   show_line_diagnostics);
+IDE_AVAILABLE_IN_3_32
+void     ide_gutter_style_changed             (IdeGutter *self);
+
+G_END_DECLS
diff --git a/src/libide/hover/ide-hover-context-private.h b/src/libide/sourceview/ide-hover-context-private.h
similarity index 95%
rename from src/libide/hover/ide-hover-context-private.h
rename to src/libide/sourceview/ide-hover-context-private.h
index d816a826c..2e3c9ce72 100644
--- a/src/libide/hover/ide-hover-context-private.h
+++ b/src/libide/sourceview/ide-hover-context-private.h
@@ -21,10 +21,10 @@
 #pragma once
 
 #include <gtk/gtk.h>
+#include <libide-code.h>
 
-#include "hover/ide-hover-context.h"
-#include "hover/ide-hover-provider.h"
-#include "util/ide-marked-content.h"
+#include "ide-hover-context.h"
+#include "ide-hover-provider.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/hover/ide-hover-context.c b/src/libide/sourceview/ide-hover-context.c
similarity index 97%
rename from src/libide/hover/ide-hover-context.c
rename to src/libide/sourceview/ide-hover-context.c
index 4a7274eae..1cf6c5485 100644
--- a/src/libide/hover/ide-hover-context.c
+++ b/src/libide/sourceview/ide-hover-context.c
@@ -22,10 +22,11 @@
 
 #include "config.h"
 
-#include "hover/ide-hover-context.h"
-#include "hover/ide-hover-context-private.h"
-#include "hover/ide-hover-provider.h"
-#include "threading/ide-task.h"
+#include <libide-threading.h>
+
+#include "ide-hover-context.h"
+#include "ide-hover-context-private.h"
+#include "ide-hover-provider.h"
 
 struct _IdeHoverContext
 {
diff --git a/src/libide/hover/ide-hover-context.h b/src/libide/sourceview/ide-hover-context.h
similarity index 89%
rename from src/libide/hover/ide-hover-context.h
rename to src/libide/sourceview/ide-hover-context.h
index 5cd01dbaa..0f42bec24 100644
--- a/src/libide/hover/ide-hover-context.h
+++ b/src/libide/sourceview/ide-hover-context.h
@@ -20,12 +20,13 @@
 
 #pragma once
 
-#include <gio/gio.h>
-#include <gtk/gtk.h>
-
-#include "ide-version-macros.h"
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "util/ide-marked-content.h"
+#include <gtk/gtk.h>
+#include <libide-core.h>
+#include <libide-code.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/hover/ide-hover-popover-private.h b/src/libide/sourceview/ide-hover-popover-private.h
similarity index 100%
rename from src/libide/hover/ide-hover-popover-private.h
rename to src/libide/sourceview/ide-hover-popover-private.h
diff --git a/src/libide/hover/ide-hover-popover.c b/src/libide/sourceview/ide-hover-popover.c
similarity index 98%
rename from src/libide/hover/ide-hover-popover.c
rename to src/libide/sourceview/ide-hover-popover.c
index 671f8da46..c784e309a 100644
--- a/src/libide/hover/ide-hover-popover.c
+++ b/src/libide/sourceview/ide-hover-popover.c
@@ -23,11 +23,12 @@
 #include "config.h"
 
 #include <dazzle.h>
+#include <libide-code.h>
+#include <libide-gui.h>
 #include <string.h>
 
-#include "hover/ide-hover-context-private.h"
-#include "hover/ide-hover-popover-private.h"
-#include "util/ide-marked-view.h"
+#include "ide-hover-context-private.h"
+#include "ide-hover-popover-private.h"
 
 struct _IdeHoverPopover
 {
@@ -265,7 +266,7 @@ ide_hover_popover_class_init (IdeHoverPopoverClass *klass)
                          "The position that the hover originated in buffer coordinates",
                          GDK_TYPE_RECTANGLE,
                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 }
 
diff --git a/src/libide/hover/ide-hover-private.h b/src/libide/sourceview/ide-hover-private.h
similarity index 95%
rename from src/libide/hover/ide-hover-private.h
rename to src/libide/sourceview/ide-hover-private.h
index f2a2abfc8..3c80141ef 100644
--- a/src/libide/hover/ide-hover-private.h
+++ b/src/libide/sourceview/ide-hover-private.h
@@ -20,9 +20,7 @@
 
 #pragma once
 
-#include "ide-context.h"
-
-#include "sourceview/ide-source-view.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/hover/ide-hover-provider.c b/src/libide/sourceview/ide-hover-provider.c
similarity index 98%
rename from src/libide/hover/ide-hover-provider.c
rename to src/libide/sourceview/ide-hover-provider.c
index 2f42b7c58..079dc1007 100644
--- a/src/libide/hover/ide-hover-provider.c
+++ b/src/libide/sourceview/ide-hover-provider.c
@@ -22,8 +22,8 @@
 
 #include "config.h"
 
-#include "hover/ide-hover-provider.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-hover-provider.h"
+#include "ide-source-view.h"
 
 G_DEFINE_INTERFACE (IdeHoverProvider, ide_hover_provider, G_TYPE_OBJECT)
 
@@ -107,7 +107,7 @@ ide_hover_provider_unload (IdeHoverProvider *self,
  * @callback: a #GAsyncReadyCallback to execute upon completion
  * @user_data: closure data for @callback
  *
- * 
+ *
  * Since: 3.32
  */
 void
diff --git a/src/libide/hover/ide-hover-provider.h b/src/libide/sourceview/ide-hover-provider.h
similarity index 93%
rename from src/libide/hover/ide-hover-provider.h
rename to src/libide/sourceview/ide-hover-provider.h
index 60d66f7ca..0f11e881c 100644
--- a/src/libide/hover/ide-hover-provider.h
+++ b/src/libide/sourceview/ide-hover-provider.h
@@ -20,12 +20,14 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <gtk/gtk.h>
 
-#include "hover/ide-hover-context.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-hover-context.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/hover/ide-hover.c b/src/libide/sourceview/ide-hover.c
similarity index 96%
rename from src/libide/hover/ide-hover.c
rename to src/libide/sourceview/ide-hover.c
index fb523f946..218fb9644 100644
--- a/src/libide/hover/ide-hover.c
+++ b/src/libide/sourceview/ide-hover.c
@@ -23,15 +23,14 @@
 #include "config.h"
 
 #include <dazzle.h>
+#include <libide-code.h>
+#include <libide-plugins.h>
 #include <libpeas/peas.h>
 #include <string.h>
 
-#include "hover/ide-hover-popover-private.h"
-#include "hover/ide-hover-private.h"
-#include "hover/ide-hover-provider.h"
-#include "plugins/ide-extension-set-adapter.h"
-#include "sourceview/ide-source-iter.h"
-#include "util/ide-gtk.h"
+#include "ide-hover-popover-private.h"
+#include "ide-hover-private.h"
+#include "ide-hover-provider.h"
 
 #define GRACE_X 20
 #define GRACE_Y 20
@@ -541,7 +540,6 @@ ide_hover_motion_notify_event_cb (IdeHover             *self,
                                   IdeSourceView        *view)
 {
   GdkWindow *window;
-  gint width;
 
   g_assert (IDE_IS_HOVER (self));
   g_assert (event != NULL);
@@ -549,10 +547,14 @@ ide_hover_motion_notify_event_cb (IdeHover             *self,
   g_assert (IDE_IS_SOURCE_VIEW (view));
 
   window = gtk_text_view_get_window (GTK_TEXT_VIEW (view), GTK_TEXT_WINDOW_LEFT);
-  width = gdk_window_get_width (window);
 
-  self->motion_x = event->x + width;
-  self->motion_y = event->y;
+  if (window != NULL)
+    {
+      gint left_width = gdk_window_get_width (window);
+
+      self->motion_x = event->x + left_width;
+      self->motion_y = event->y;
+    }
 
   /*
    * If we have a popover displayed, get it's allocation so that
@@ -621,7 +623,7 @@ ide_hover_dispose (GObject *object)
 {
   IdeHover *self = (IdeHover *)object;
 
-  g_clear_object (&self->providers);
+  ide_clear_and_destroy_object (&self->providers);
 
   dzl_clear_source (&self->delay_display_source);
   dzl_clear_source (&self->dismiss_source);
@@ -753,21 +755,21 @@ _ide_hover_set_context (IdeHover   *self,
   if (self->providers != NULL)
     return;
 
-  self->providers = ide_extension_set_adapter_new (context,
+  self->providers = ide_extension_set_adapter_new (IDE_OBJECT (context),
                                                    peas_engine_get_default (),
                                                    IDE_TYPE_HOVER_PROVIDER,
                                                    "Hover-Provider-Languages",
                                                    NULL);
 
-  g_signal_connect (self->providers,
-                    "extension-added",
-                    G_CALLBACK (ide_hover_extension_added_cb),
-                    self);
+  g_signal_connect_object (self->providers,
+                           "extension-added",
+                           G_CALLBACK (ide_hover_extension_added_cb),
+                           self, 0);
 
-  g_signal_connect (self->providers,
-                    "extension-removed",
-                    G_CALLBACK (ide_hover_extension_removed_cb),
-                    self);
+  g_signal_connect_object (self->providers,
+                           "extension-removed",
+                           G_CALLBACK (ide_hover_extension_removed_cb),
+                           self, 0);
 
   ide_extension_set_adapter_foreach (self->providers,
                                      ide_hover_extension_added_cb,
diff --git a/src/libide/sourceview/ide-indenter.c b/src/libide/sourceview/ide-indenter.c
index c5f317615..6834952fd 100644
--- a/src/libide/sourceview/ide-indenter.c
+++ b/src/libide/sourceview/ide-indenter.c
@@ -22,10 +22,9 @@
 
 #include "config.h"
 
-#include "ide-context.h"
-#include "ide-debug.h"
+#include <libide-code.h>
 
-#include "sourceview/ide-indenter.h"
+#include "ide-indenter.h"
 
 G_DEFINE_INTERFACE (IdeIndenter, ide_indenter, IDE_TYPE_OBJECT)
 
diff --git a/src/libide/sourceview/ide-indenter.h b/src/libide/sourceview/ide-indenter.h
index 8f6b3aab2..226fab823 100644
--- a/src/libide/sourceview/ide-indenter.h
+++ b/src/libide/sourceview/ide-indenter.h
@@ -20,11 +20,12 @@
 
 #pragma once
 
-#include <gtk/gtk.h>
-
-#include "ide-version-macros.h"
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-object.h"
+#include <gtk/gtk.h>
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/sourceview/ide-line-change-gutter-renderer.c 
b/src/libide/sourceview/ide-line-change-gutter-renderer.c
index 9d5a068c4..a8904959c 100644
--- a/src/libide/sourceview/ide-line-change-gutter-renderer.c
+++ b/src/libide/sourceview/ide-line-change-gutter-renderer.c
@@ -22,19 +22,15 @@
 
 #include "config.h"
 
-#include "ide-context.h"
+#include <libide-code.h>
 
-#include "buffers/ide-buffer.h"
-#include "files/ide-file.h"
-#include "sourceview/ide-line-change-gutter-renderer.h"
-#include "vcs/ide-vcs.h"
+#include "ide-line-change-gutter-renderer.h"
 
 #define DELETE_WIDTH  5.0
 #define DELETE_HEIGHT 8.0
 
-#if 0
-# define ARROW_TOWARDS_GUTTER
-#endif
+#define IS_LINE_CHANGE(i) ((i)->is_add || (i)->is_change || \
+                           (i)->is_delete || (i)->is_next_delete || (i)->is_prev_delete)
 
 struct _IdeLineChangeGutterRenderer
 {
@@ -46,33 +42,81 @@ struct _IdeLineChangeGutterRenderer
   GtkTextBuffer          *buffer;
   gulong                  buffer_notify_style_scheme;
 
-  GdkRGBA                 rgba_added;
-  GdkRGBA                 rgba_changed;
-  GdkRGBA                 rgba_removed;
+  GArray                 *lines;
+  guint                   begin_line;
 
-  guint                   show_line_deletions : 1;
+  struct {
+    GdkRGBA add;
+    GdkRGBA remove;
+    GdkRGBA change;
+  } changes;
 
   guint                   rgba_added_set : 1;
   guint                   rgba_changed_set : 1;
   guint                   rgba_removed_set : 1;
 };
 
+typedef struct
+{
+  /* The line is an addition to the buffer */
+  guint is_add : 1;
+
+  /* The line has changed in the buffer */
+  guint is_change : 1;
+
+  /* The line is part of a deleted range in the buffer */
+  guint is_delete : 1;
 
-G_DEFINE_TYPE (IdeLineChangeGutterRenderer,
-               ide_line_change_gutter_renderer,
-               GTK_SOURCE_TYPE_GUTTER_RENDERER)
+  /* The previous line was a delete */
+  guint is_prev_delete : 1;
 
-static GdkRGBA rgbaAdded;
-static GdkRGBA rgbaChanged;
-static GdkRGBA rgbaRemoved;
+  /* The next line is a delete */
+  guint is_next_delete : 1;
+} LineInfo;
 
 enum {
-  PROP_0,
-  PROP_SHOW_LINE_DELETIONS,
-  LAST_PROP
+  FOREGROUND,
+  BACKGROUND,
 };
 
-static GParamSpec *properties [LAST_PROP];
+G_DEFINE_TYPE (IdeLineChangeGutterRenderer, ide_line_change_gutter_renderer, GTK_SOURCE_TYPE_GUTTER_RENDERER)
+
+static gboolean
+get_style_rgba (GtkSourceStyleScheme *scheme,
+                const gchar          *style_name,
+                int                   type,
+                GdkRGBA              *rgba)
+{
+  GtkSourceStyle *style;
+
+  g_assert (!scheme || GTK_SOURCE_IS_STYLE_SCHEME (scheme));
+  g_assert (style_name != NULL);
+  g_assert (type == FOREGROUND || type == BACKGROUND);
+  g_assert (rgba != NULL);
+
+  memset (rgba, 0, sizeof *rgba);
+
+  if (scheme == NULL)
+    return FALSE;
+
+  if (NULL != (style = gtk_source_style_scheme_get_style (scheme, style_name)))
+    {
+      g_autofree gchar *str = NULL;
+      gboolean set = FALSE;
+
+      g_object_get (style,
+                    type ? "background" : "foreground", &str,
+                    type ? "background-set" : "foreground-set", &set,
+                    NULL);
+
+      if (str != NULL)
+        gdk_rgba_parse (rgba, str);
+
+      return set;
+    }
+
+  return FALSE;
+}
 
 static void
 disconnect_style_scheme (IdeLineChangeGutterRenderer *self)
@@ -111,70 +155,25 @@ disconnect_view (IdeLineChangeGutterRenderer *self)
 static void
 connect_style_scheme (IdeLineChangeGutterRenderer *self)
 {
-  GtkTextView *text_view;
+  GtkSourceStyleScheme *scheme;
   GtkTextBuffer *buffer;
-  GtkSourceStyleScheme *style_scheme;
-
-  text_view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
-  buffer = gtk_text_view_get_buffer (text_view);
+  GtkTextView *view;
 
-  if (!GTK_SOURCE_IS_BUFFER (buffer))
+  if (!(view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self))) ||
+      !(buffer = gtk_text_view_get_buffer (view)) ||
+      !GTK_SOURCE_IS_BUFFER (buffer))
     return;
 
-  style_scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
-
-  if (style_scheme)
-    {
-      GtkSourceStyle *style;
-
-      style = gtk_source_style_scheme_get_style (style_scheme, "gutter:added-line");
-
-      if (style)
-        {
-          g_autofree gchar *foreground = NULL;
-          gboolean foreground_set = 0;
-
-          g_object_get (style,
-                        "foreground-set", &foreground_set,
-                        "foreground", &foreground,
-                        NULL);
+  scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (buffer));
 
-          if (foreground_set)
-            self->rgba_added_set = gdk_rgba_parse (&self->rgba_added, foreground);
-        }
+  if (!get_style_rgba (scheme, "gutter::added-line", FOREGROUND, &self->changes.add))
+    gdk_rgba_parse (&self->changes.add, "#8ae234");
 
-      style = gtk_source_style_scheme_get_style (style_scheme, "gutter:changed-line");
+  if (!get_style_rgba (scheme, "gutter::changed-line", FOREGROUND, &self->changes.change))
+    gdk_rgba_parse (&self->changes.change, "#fcaf3e");
 
-      if (style)
-        {
-          g_autofree gchar *foreground = NULL;
-          gboolean foreground_set = 0;
-
-          g_object_get (style,
-                        "foreground-set", &foreground_set,
-                        "foreground", &foreground,
-                        NULL);
-
-          if (foreground_set)
-            self->rgba_changed_set = gdk_rgba_parse (&self->rgba_changed, foreground);
-        }
-
-      style = gtk_source_style_scheme_get_style (style_scheme, "gutter:removed-line");
-
-      if (style)
-        {
-          g_autofree gchar *foreground = NULL;
-          gboolean foreground_set = 0;
-
-          g_object_get (style,
-                        "foreground-set", &foreground_set,
-                        "foreground", &foreground,
-                        NULL);
-
-          if (foreground_set)
-            self->rgba_removed_set = gdk_rgba_parse (&self->rgba_removed, foreground);
-        }
-    }
+  if (!get_style_rgba (scheme, "gutter::removed-line", FOREGROUND, &self->changes.remove))
+    gdk_rgba_parse (&self->changes.remove, "#ef2929");
 }
 
 static void
@@ -239,199 +238,187 @@ ide_line_change_gutter_renderer_notify_view (IdeLineChangeGutterRenderer *self)
 }
 
 static void
-ide_line_change_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
-                                      cairo_t                      *cr,
-                                      GdkRectangle                 *bg_area,
-                                      GdkRectangle                 *cell_area,
-                                      GtkTextIter                  *begin,
-                                      GtkTextIter                  *end,
-                                      GtkSourceGutterRendererState  state)
+populate_changes_cb (guint               line,
+                     IdeBufferLineChange change,
+                     gpointer            user_data)
 {
-  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
-  GdkRectangle cell_area_copy;
-  GtkTextBuffer *buffer;
-  GdkRGBA *rgba = NULL;
-  IdeBufferLineFlags flags;
-  IdeBufferLineFlags prev_flags = 0;
-  IdeBufferLineFlags next_flags;
-  guint lineno;
-  gint xpad;
+  LineInfo *info;
+  struct {
+    GArray *lines;
+    guint   begin_line;
+    guint   end_line;
+  } *state = user_data;
+  guint pos;
+
+  g_assert (line >= state->begin_line);
+  g_assert (line <= state->end_line);
+
+  pos = line - state->begin_line;
 
-  g_return_if_fail (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
-  g_return_if_fail (cr);
-  g_return_if_fail (bg_area);
-  g_return_if_fail (cell_area);
-  g_return_if_fail (begin);
-  g_return_if_fail (end);
+  info = &g_array_index (state->lines, LineInfo, pos);
+  info->is_add = !!(change & IDE_BUFFER_LINE_CHANGE_ADDED);
+  info->is_change = !!(change & IDE_BUFFER_LINE_CHANGE_CHANGED);
+  info->is_delete = !!(change & IDE_BUFFER_LINE_CHANGE_DELETED);
 
-  GTK_SOURCE_GUTTER_RENDERER_CLASS (ide_line_change_gutter_renderer_parent_class)->draw (renderer, cr, 
bg_area, cell_area, begin, end, state);
+  if (pos > 0)
+    {
+      LineInfo *last = &g_array_index (state->lines, LineInfo, pos - 1);
 
-  buffer = gtk_text_iter_get_buffer (begin);
+      info->is_prev_delete = last->is_delete;
+      last->is_next_delete = info->is_delete;
+    }
+}
 
-  if (!IDE_IS_BUFFER (buffer))
+static void
+ide_line_change_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+                                       cairo_t                 *cr,
+                                       GdkRectangle            *bg_area,
+                                       GdkRectangle            *cell_area,
+                                       GtkTextIter             *begin,
+                                       GtkTextIter             *end)
+{
+  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
+  IdeBufferChangeMonitor *monitor;
+  GtkTextBuffer *buffer;
+  GtkTextView *view;
+  struct {
+    GArray *lines;
+    guint   begin_line;
+    guint   end_line;
+  } state;
+
+  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+  g_assert (cell_area != NULL);
+  g_assert (begin != NULL);
+  g_assert (end != NULL);
+
+  if (!(view = gtk_source_gutter_renderer_get_view (renderer)) ||
+      !(buffer = gtk_text_view_get_buffer (view)) ||
+      !IDE_IS_BUFFER (buffer) ||
+      !(monitor = ide_buffer_get_change_monitor (IDE_BUFFER (buffer))))
     return;
 
-  lineno = gtk_text_iter_get_line (begin);
+  self->begin_line = state.begin_line = gtk_text_iter_get_line (begin);
+  state.end_line = gtk_text_iter_get_line (end);
+  state.lines = g_array_new (FALSE, TRUE, sizeof (LineInfo));
+  g_array_set_size (state.lines, state.end_line - state.begin_line + 1);
 
-  flags = ide_buffer_get_line_flags (IDE_BUFFER (buffer), lineno);
-  next_flags = ide_buffer_get_line_flags (IDE_BUFFER (buffer), lineno + 1);
-  if (lineno > 0)
-    prev_flags = ide_buffer_get_line_flags (IDE_BUFFER (buffer), lineno - 1);
+  ide_buffer_change_monitor_foreach_change (monitor,
+                                            state.begin_line,
+                                            state.end_line,
+                                            populate_changes_cb,
+                                            &state);
 
-  if ((flags & IDE_BUFFER_LINE_FLAGS_ADDED) != 0)
-    rgba = self->rgba_added_set ? &self->rgba_added : &rgbaAdded;
+  g_clear_pointer (&self->lines, g_array_unref);
+  self->lines = g_steal_pointer (&state.lines);
+}
 
-  if ((flags & IDE_BUFFER_LINE_FLAGS_CHANGED) != 0)
-    rgba = self->rgba_changed_set ? &self->rgba_changed : &rgbaChanged;
+static void
+ide_line_change_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
 
-  if (rgba)
-    {
-      gdk_cairo_rectangle (cr, cell_area);
-      gdk_cairo_set_source_rgba (cr, rgba);
-      cairo_fill (cr);
-    }
+  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
 
-  if (!self->show_line_deletions)
-    return;
+  //g_clear_pointer (&self->lines, g_array_unref);
+}
 
-  /*
-   * If we have xpad, we want to draw over it. So we'll just mutate
-   * the cell_area here.
-   */
-  g_object_get (self, "xpad", &xpad, NULL);
-  cell_area_copy = *cell_area;
-  cell_area->x += xpad;
+static void
+draw_line_change (IdeLineChangeGutterRenderer  *self,
+                  cairo_t                      *cr,
+                  GdkRectangle                 *area,
+                  LineInfo                     *info,
+                  GtkSourceGutterRendererState  state)
+{
+  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
 
   /*
-   * If the next line is a deletion, but we were not a deletion, then
-   * draw our half the deletion mark.
+   * Draw a simple line with the appropriate color from the style scheme
+   * based on the type of change we have.
    */
-  if (((next_flags & IDE_BUFFER_LINE_FLAGS_DELETED) != 0) &&
-      ((flags & IDE_BUFFER_LINE_FLAGS_DELETED) == 0))
+
+  if (info->is_add || info->is_change)
     {
-      rgba = self->rgba_removed_set ? &self->rgba_removed : &rgbaRemoved;
-      gdk_cairo_set_source_rgba (cr, rgba);
-
-#ifdef ARROW_TOWARDS_GUTTER
-      cairo_move_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + cell_area->height);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y + cell_area->height);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + cell_area->height - (DELETE_HEIGHT / 2));
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + cell_area->height);
-#else
-      cairo_move_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + cell_area->height);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y + cell_area->height);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y + cell_area->height - (DELETE_HEIGHT / 2));
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + cell_area->height);
-#endif
+      gdk_cairo_rectangle (cr, area);
+
+      if (info->is_add)
+        gdk_cairo_set_source_rgba (cr, &self->changes.add);
+      else
+        gdk_cairo_set_source_rgba (cr, &self->changes.change);
 
       cairo_fill (cr);
     }
 
-  /*
-   * If the previous line was not a deletion, and we have a deletion, then
-   * draw our half the deletion mark.
-   */
-  if (((prev_flags & IDE_BUFFER_LINE_FLAGS_DELETED) == 0) &&
-      ((flags & IDE_BUFFER_LINE_FLAGS_DELETED) != 0))
+  if (info->is_next_delete && !info->is_delete)
     {
-      rgba = self->rgba_removed_set ? &self->rgba_removed : &rgbaRemoved;
-      gdk_cairo_set_source_rgba (cr, rgba);
-
-#ifdef ARROW_TOWARDS_GUTTER
-      cairo_move_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y + (DELETE_HEIGHT / 2));
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y);
-#else
-      cairo_move_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y);
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width - DELETE_WIDTH,
-                     cell_area->y + (DELETE_HEIGHT / 2));
-      cairo_line_to (cr,
-                     cell_area->x + cell_area->width,
-                     cell_area->y);
-#endif
-
+      cairo_rectangle (cr,
+                       area->x,
+                       area->y + area->width / 2.0,
+                       area->width,
+                       area->height / 2.0);
+      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
       cairo_fill (cr);
     }
 
-  *cell_area = cell_area_copy;
+  if (info->is_delete && !info->is_prev_delete)
+    {
+      cairo_rectangle (cr,
+                       area->x,
+                       area->y,
+                       area->width,
+                       area->height / 2.0);
+      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
+      cairo_fill (cr);
+    }
 }
 
 static void
-ide_line_change_gutter_renderer_dispose (GObject *object)
+ide_line_change_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
+                                      cairo_t                      *cr,
+                                      GdkRectangle                 *bg_area,
+                                      GdkRectangle                 *cell_area,
+                                      GtkTextIter                  *begin,
+                                      GtkTextIter                  *end,
+                                      GtkSourceGutterRendererState  state)
 {
-  disconnect_view (IDE_LINE_CHANGE_GUTTER_RENDERER (object));
+  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
+  guint line;
 
-  G_OBJECT_CLASS (ide_line_change_gutter_renderer_parent_class)->dispose (object);
-}
+  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+  g_assert (cell_area != NULL);
+  g_assert (begin != NULL);
+  g_assert (end != NULL);
 
-static void
-ide_line_change_gutter_renderer_get_property (GObject    *object,
-                                              guint       prop_id,
-                                              GValue     *value,
-                                              GParamSpec *pspec)
-{
-  IdeLineChangeGutterRenderer *self = IDE_LINE_CHANGE_GUTTER_RENDERER(object);
+  if (self->lines == NULL)
+    return;
+
+  line = gtk_text_iter_get_line (begin);
 
-  switch (prop_id)
+  if ((line - self->begin_line) < self->lines->len)
     {
-    case PROP_SHOW_LINE_DELETIONS:
-      g_value_set_boolean (value, self->show_line_deletions);
-      break;
+      LineInfo *info = &g_array_index (self->lines, LineInfo, line - self->begin_line);
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      if (IS_LINE_CHANGE (info))
+        draw_line_change (self, cr, cell_area, info, state);
     }
 }
 
 static void
-ide_line_change_gutter_renderer_set_property (GObject      *object,
-                                              guint         prop_id,
-                                              const GValue *value,
-                                              GParamSpec   *pspec)
+ide_line_change_gutter_renderer_dispose (GObject *object)
 {
-  IdeLineChangeGutterRenderer *self = IDE_LINE_CHANGE_GUTTER_RENDERER(object);
+  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)object;
 
-  switch (prop_id)
-    {
-    case PROP_SHOW_LINE_DELETIONS:
-      self->show_line_deletions = g_value_get_boolean (value);
-      gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (self));
-      break;
+  disconnect_view (IDE_LINE_CHANGE_GUTTER_RENDERER (object));
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-    }
+  g_clear_pointer (&self->lines, g_array_unref);
+
+  G_OBJECT_CLASS (ide_line_change_gutter_renderer_parent_class)->dispose (object);
 }
 
 static void
@@ -441,23 +428,10 @@ ide_line_change_gutter_renderer_class_init (IdeLineChangeGutterRendererClass *kl
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = ide_line_change_gutter_renderer_dispose;
-  object_class->get_property = ide_line_change_gutter_renderer_get_property;
-  object_class->set_property = ide_line_change_gutter_renderer_set_property;
 
+  renderer_class->end = ide_line_change_gutter_renderer_end;
+  renderer_class->begin = ide_line_change_gutter_renderer_begin;
   renderer_class->draw = ide_line_change_gutter_renderer_draw;
-
-  properties [PROP_SHOW_LINE_DELETIONS] =
-    g_param_spec_boolean ("show-line-deletions",
-                          "Show Line Deletions",
-                          "If the deletion mark should be shown for deleted lines",
-                          FALSE,
-                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_properties (object_class, LAST_PROP, properties);
-
-  gdk_rgba_parse (&rgbaAdded, "#8ae234");
-  gdk_rgba_parse (&rgbaChanged, "#fcaf3e");
-  gdk_rgba_parse (&rgbaRemoved, "#ff0000");
 }
 
 static void
diff --git a/src/libide/sourceview/ide-line-change-gutter-renderer.h 
b/src/libide/sourceview/ide-line-change-gutter-renderer.h
index e7e9ffd13..244e6bb89 100644
--- a/src/libide/sourceview/ide-line-change-gutter-renderer.h
+++ b/src/libide/sourceview/ide-line-change-gutter-renderer.h
@@ -21,12 +21,13 @@
 #pragma once
 
 #include <gtksourceview/gtksource.h>
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_LINE_CHANGE_GUTTER_RENDERER (ide_line_change_gutter_renderer_get_type())
 
-G_DECLARE_FINAL_TYPE (IdeLineChangeGutterRenderer, ide_line_change_gutter_renderer,
-                      IDE, LINE_CHANGE_GUTTER_RENDERER, GtkSourceGutterRenderer);
+IDE_AVAILABLE_IN_3_32
+G_DECLARE_FINAL_TYPE (IdeLineChangeGutterRenderer, ide_line_change_gutter_renderer, IDE, 
LINE_CHANGE_GUTTER_RENDERER, GtkSourceGutterRenderer)
 
 G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet-chunk.c b/src/libide/sourceview/ide-snippet-chunk.c
similarity index 100%
rename from src/libide/snippets/ide-snippet-chunk.c
rename to src/libide/sourceview/ide-snippet-chunk.c
diff --git a/src/libide/snippets/ide-snippet-chunk.h b/src/libide/sourceview/ide-snippet-chunk.h
similarity index 92%
rename from src/libide/snippets/ide-snippet-chunk.h
rename to src/libide/sourceview/ide-snippet-chunk.h
index 75b7bd47e..a519f7b1f 100644
--- a/src/libide/snippets/ide-snippet-chunk.h
+++ b/src/libide/sourceview/ide-snippet-chunk.h
@@ -20,11 +20,13 @@
 
 #pragma once
 
-#include <glib-object.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <libide-core.h>
 
-#include "snippets/ide-snippet-context.h"
+#include "ide-snippet-context.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/snippets/ide-snippet-context.c b/src/libide/sourceview/ide-snippet-context.c
similarity index 100%
rename from src/libide/snippets/ide-snippet-context.c
rename to src/libide/sourceview/ide-snippet-context.c
diff --git a/src/libide/snippets/ide-snippet-context.h b/src/libide/sourceview/ide-snippet-context.h
similarity index 94%
rename from src/libide/snippets/ide-snippet-context.h
rename to src/libide/sourceview/ide-snippet-context.h
index 77a5e4722..55ee3943a 100644
--- a/src/libide/snippets/ide-snippet-context.h
+++ b/src/libide/sourceview/ide-snippet-context.h
@@ -20,9 +20,11 @@
 
 #pragma once
 
-#include <glib-object.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/snippets/ide-snippet-parser.c b/src/libide/sourceview/ide-snippet-parser.c
similarity index 98%
rename from src/libide/snippets/ide-snippet-parser.c
rename to src/libide/sourceview/ide-snippet-parser.c
index 5231611bf..f094b9f1d 100644
--- a/src/libide/snippets/ide-snippet-parser.c
+++ b/src/libide/sourceview/ide-snippet-parser.c
@@ -24,13 +24,13 @@
 
 #include <errno.h>
 #include <glib/gi18n.h>
+#include <libide-io.h>
 #include <stdlib.h>
 
-#include "snippets/ide-snippet.h"
-#include "snippets/ide-snippet-chunk.h"
-#include "snippets/ide-snippet-parser.h"
-#include "snippets/ide-snippet-private.h"
-#include "util/ide-line-reader.h"
+#include "ide-snippet.h"
+#include "ide-snippet-chunk.h"
+#include "ide-snippet-parser.h"
+#include "ide-snippet-private.h"
 
 /**
  * SECTION:ide-snippet-parser
diff --git a/src/libide/snippets/ide-snippet-parser.h b/src/libide/sourceview/ide-snippet-parser.h
similarity index 92%
rename from src/libide/snippets/ide-snippet-parser.h
rename to src/libide/sourceview/ide-snippet-parser.h
index 9fac6aab2..c45662273 100644
--- a/src/libide/snippets/ide-snippet-parser.h
+++ b/src/libide/sourceview/ide-snippet-parser.h
@@ -20,6 +20,10 @@
 
 #pragma once
 
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
 #include <gio/gio.h>
 
 #include "ide-version-macros.h"
diff --git a/src/libide/snippets/ide-snippet-private.h b/src/libide/sourceview/ide-snippet-private.h
similarity index 100%
rename from src/libide/snippets/ide-snippet-private.h
rename to src/libide/sourceview/ide-snippet-private.h
diff --git a/src/libide/snippets/ide-snippet-storage.c b/src/libide/sourceview/ide-snippet-storage.c
similarity index 88%
rename from src/libide/snippets/ide-snippet-storage.c
rename to src/libide/sourceview/ide-snippet-storage.c
index a172dd36f..38ad6c774 100644
--- a/src/libide/snippets/ide-snippet-storage.c
+++ b/src/libide/sourceview/ide-snippet-storage.c
@@ -22,11 +22,11 @@
 
 #include "config.h"
 
+#include <libide-io.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "snippets/ide-snippet-storage.h"
-#include "util/ide-line-reader.h"
+#include "ide-snippet-storage.h"
 
 #define SNIPPETS_DIRECTORY "/org/gnome/builder/snippets/"
 
@@ -51,7 +51,7 @@
 
 struct _IdeSnippetStorage
 {
-  GObject       parent_instance;
+  IdeObject     parent_instance;
   GStringChunk *strings;
   GArray       *infos;
   GPtrArray    *bytes;
@@ -68,7 +68,10 @@ typedef struct
   const gchar *endptr;
 } LoadState;
 
-G_DEFINE_TYPE (IdeSnippetStorage, ide_snippet_storage, G_TYPE_OBJECT)
+static void async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeSnippetStorage, ide_snippet_storage, IDE_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init))
 
 static void
 ide_snippet_storage_finalize (GObject *object)
@@ -285,7 +288,7 @@ query_compare (gconstpointer a,
   const IdeSnippetInfo *ai = a;
   const IdeSnippetInfo *bi = b;
   gboolean r;
-  
+
   if (!(r = g_strcmp0 (ai->lang, bi->lang)))
     {
       if (g_str_has_prefix (bi->name, ai->name))
@@ -366,12 +369,14 @@ ide_snippet_storage_query (IdeSnippetStorage        *self,
     }
 }
 
-void
-ide_snippet_storage_load_async (IdeSnippetStorage   *self,
+static void
+ide_snippet_storage_init_async (GAsyncInitable      *initable,
+                                gint                 io_priority,
                                 GCancellable        *cancellable,
                                 GAsyncReadyCallback  callback,
                                 gpointer             user_data)
 {
+  IdeSnippetStorage *self = (IdeSnippetStorage *)initable;
   g_autofree gchar *local = NULL;
   g_autoptr(GTask) task = NULL;
   g_autoptr(GDir) dir = NULL;
@@ -382,7 +387,7 @@ ide_snippet_storage_load_async (IdeSnippetStorage   *self,
   g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
 
   task = g_task_new (self, cancellable, callback, user_data);
-  g_task_set_source_tag (task, ide_snippet_storage_load_async);
+  g_task_set_source_tag (task, ide_snippet_storage_init_async);
 
   if (self->loaded)
     {
@@ -454,13 +459,45 @@ ide_snippet_storage_load_async (IdeSnippetStorage   *self,
   g_task_return_boolean (task, TRUE);
 }
 
-gboolean
-ide_snippet_storage_load_finish (IdeSnippetStorage  *self,
-                                 GAsyncResult       *result,
-                                 GError            **error)
+static gboolean
+ide_snippet_storage_init_finish (GAsyncInitable  *initable,
+                                 GAsyncResult    *result,
+                                 GError         **error)
 {
-  g_return_val_if_fail (IDE_IS_SNIPPET_STORAGE (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET_STORAGE (initable), FALSE);
   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 
   return g_task_propagate_boolean (G_TASK (result), error);
 }
+
+static void
+async_initable_iface_init (GAsyncInitableIface *iface)
+{
+  iface->init_async = ide_snippet_storage_init_async;
+  iface->init_finish = ide_snippet_storage_init_finish;
+}
+
+/**
+ * ide_snippet_storage_from_context:
+ * @context: an #IdeContext
+ *
+ * Gets the snippet storage for the context.
+ *
+ * Returns: (transfer none): an #IdeSnippetStorage
+ *
+ * Since: 3.32
+ */
+IdeSnippetStorage *
+ide_snippet_storage_from_context (IdeContext *context)
+{
+  IdeSnippetStorage *ret;
+
+  g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
+  g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
+
+  /* Give back a borrowed reference instead of full */
+  ret = ide_object_ensure_child_typed (IDE_OBJECT (context), IDE_TYPE_SNIPPET_STORAGE);
+  g_object_unref (ret);
+
+  return ret;
+}
diff --git a/src/libide/snippets/ide-snippet-storage.h b/src/libide/sourceview/ide-snippet-storage.h
similarity index 77%
rename from src/libide/snippets/ide-snippet-storage.h
rename to src/libide/sourceview/ide-snippet-storage.h
index 1b3dc8ed2..b3fde8d96 100644
--- a/src/libide/snippets/ide-snippet-storage.h
+++ b/src/libide/sourceview/ide-snippet-storage.h
@@ -20,10 +20,13 @@
 
 #pragma once
 
-#include <gio/gio.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-types.h"
-#include "ide-version-macros.h"
+#include <libide-core.h>
+
+#include "ide-snippet-types.h"
 
 G_BEGIN_DECLS
 
@@ -46,8 +49,10 @@ typedef void (*IdeSnippetStorageForeach) (IdeSnippetStorage    *self,
                                           gpointer              user_data);
 
 IDE_AVAILABLE_IN_3_32
-G_DECLARE_FINAL_TYPE (IdeSnippetStorage, ide_snippet_storage, IDE, SNIPPET_STORAGE, GObject)
+G_DECLARE_FINAL_TYPE (IdeSnippetStorage, ide_snippet_storage, IDE, SNIPPET_STORAGE, IdeObject)
 
+IDE_AVAILABLE_IN_3_32
+IdeSnippetStorage *ide_snippet_storage_from_context (IdeContext *context);
 IDE_AVAILABLE_IN_3_32
 IdeSnippetStorage *ide_snippet_storage_new         (void);
 IDE_AVAILABLE_IN_3_32
@@ -64,14 +69,5 @@ void               ide_snippet_storage_query       (IdeSnippetStorage         *s
                                                     const gchar               *prefix,
                                                     IdeSnippetStorageForeach   foreach,
                                                     gpointer                   user_data);
-IDE_AVAILABLE_IN_3_32
-void               ide_snippet_storage_load_async  (IdeSnippetStorage         *self,
-                                                    GCancellable              *cancellable,
-                                                    GAsyncReadyCallback        callback,
-                                                    gpointer                   user_data);
-IDE_AVAILABLE_IN_3_32
-gboolean           ide_snippet_storage_load_finish (IdeSnippetStorage         *self,
-                                                    GAsyncResult              *result,
-                                                    GError                   **error);
 
 G_END_DECLS
diff --git a/src/libide/sourceview/ide-omni-gutter-renderer-private.h 
b/src/libide/sourceview/ide-snippet-types.h
similarity index 67%
rename from src/libide/sourceview/ide-omni-gutter-renderer-private.h
rename to src/libide/sourceview/ide-snippet-types.h
index 415e18da1..265edb633 100644
--- a/src/libide/sourceview/ide-omni-gutter-renderer-private.h
+++ b/src/libide/sourceview/ide-snippet-types.h
@@ -1,4 +1,4 @@
-/* ide-omni-gutter-renderer-private.h
+/* ide-snippet-types.h
  *
  * Copyright 2018-2019 Christian Hergert <chergert redhat com>
  *
@@ -20,10 +20,18 @@
 
 #pragma once
 
-#include "ide-omni-gutter-renderer.h"
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
-void _ide_omni_gutter_renderer_reset_font (IdeOmniGutterRenderer *self);
+typedef struct _IdeSnippet IdeSnippet;
+typedef struct _IdeSnippetChunk IdeSnippetChunk;
+typedef struct _IdeSnippetParser IdeSnippetParser;
+typedef struct _IdeSnippetContext IdeSnippetContext;
+typedef struct _IdeSnippetStorage IdeSnippetStorage;
 
 G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet.c b/src/libide/sourceview/ide-snippet.c
similarity index 99%
rename from src/libide/snippets/ide-snippet.c
rename to src/libide/sourceview/ide-snippet.c
index b61a790e0..12e010d68 100644
--- a/src/libide/snippets/ide-snippet.c
+++ b/src/libide/sourceview/ide-snippet.c
@@ -25,13 +25,11 @@
 #include <dazzle.h>
 #include <glib/gi18n.h>
 
-#include "ide-debug.h"
-
-#include "completion/ide-completion-proposal.h"
-#include "snippets/ide-snippet.h"
-#include "snippets/ide-snippet-private.h"
-#include "snippets/ide-snippet-chunk.h"
-#include "snippets/ide-snippet-context.h"
+#include "ide-completion-proposal.h"
+#include "ide-snippet.h"
+#include "ide-snippet-private.h"
+#include "ide-snippet-chunk.h"
+#include "ide-snippet-context.h"
 
 /**
  * SECTION:ide-snippet
@@ -991,7 +989,6 @@ ide_snippet_before_delete_range (IdeSnippet    *self,
           continue;
         }
       *run -= len;
-      len = 0;
       break;
     }
 
diff --git a/src/libide/snippets/ide-snippet.h b/src/libide/sourceview/ide-snippet.h
similarity index 94%
rename from src/libide/snippets/ide-snippet.h
rename to src/libide/sourceview/ide-snippet.h
index 001abcd7e..3a2844955 100644
--- a/src/libide/snippets/ide-snippet.h
+++ b/src/libide/sourceview/ide-snippet.h
@@ -20,10 +20,14 @@
 
 #pragma once
 
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
+
 #include <gtk/gtk.h>
+#include <libide-core.h>
 
 #include "ide-snippet-chunk.h"
-#include "ide-version-macros.h"
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/sourceview/ide-source-search-context.c 
b/src/libide/sourceview/ide-source-search-context.c
index 37465aee9..1bd7a474d 100644
--- a/src/libide/sourceview/ide-source-search-context.c
+++ b/src/libide/sourceview/ide-source-search-context.c
@@ -22,8 +22,9 @@
 
 #include "config.h"
 
-#include "sourceview/ide-source-search-context.h"
-#include "threading/ide-task.h"
+#include <libide-threading.h>
+
+#include "ide-source-search-context.h"
 
 typedef struct
 {
diff --git a/src/libide/sourceview/ide-source-search-context.h 
b/src/libide/sourceview/ide-source-search-context.h
index 2641a564b..6d83eff23 100644
--- a/src/libide/sourceview/ide-source-search-context.h
+++ b/src/libide/sourceview/ide-source-search-context.h
@@ -20,9 +20,12 @@
 
 #pragma once
 
-#include <gtksourceview/gtksource.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-version-macros.h"
+#include <gtksourceview/gtksource.h>
+#include <libide-core.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/libide/sourceview/ide-source-view-capture.c b/src/libide/sourceview/ide-source-view-capture.c
index 1595ef986..83ad8f69a 100644
--- a/src/libide/sourceview/ide-source-view-capture.c
+++ b/src/libide/sourceview/ide-source-view-capture.c
@@ -22,7 +22,8 @@
 
 #include <glib/gi18n.h>
 
-#include "sourceview/ide-source-view-capture.h"
+#include "ide-source-view-capture.h"
+#include "ide-source-view-private.h"
 
 typedef struct
 {
diff --git a/src/libide/sourceview/ide-source-view-capture.h b/src/libide/sourceview/ide-source-view-capture.h
index b57903587..c2b20b026 100644
--- a/src/libide/sourceview/ide-source-view-capture.h
+++ b/src/libide/sourceview/ide-source-view-capture.h
@@ -20,16 +20,13 @@
 
 #pragma once
 
-#include "sourceview/ide-source-view.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_SOURCE_VIEW_CAPTURE (ide_source_view_capture_get_type())
 
-G_DECLARE_FINAL_TYPE (IdeSourceViewCapture,
-                      ide_source_view_capture,
-                      IDE, SOURCE_VIEW_CAPTURE,
-                      GObject)
+G_DECLARE_FINAL_TYPE (IdeSourceViewCapture, ide_source_view_capture, IDE, SOURCE_VIEW_CAPTURE, GObject)
 
 IdeSourceViewCapture *ide_source_view_capture_new             (IdeSourceView         *view,
                                                                const gchar           *mode_name,
diff --git a/src/libide/sourceview/ide-source-view-mode.c b/src/libide/sourceview/ide-source-view-mode.c
index 08663ca8e..fc9b2366f 100644
--- a/src/libide/sourceview/ide-source-view-mode.c
+++ b/src/libide/sourceview/ide-source-view-mode.c
@@ -24,12 +24,11 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
+#include <libide-core.h>
 #include <string.h>
 
-#include "ide-debug.h"
-
-#include "sourceview/ide-source-view.h"
-#include "sourceview/ide-source-view-mode.h"
+#include "ide-source-view.h"
+#include "ide-source-view-mode.h"
 
 struct _IdeSourceViewMode
 {
diff --git a/src/libide/sourceview/ide-source-view-mode.h b/src/libide/sourceview/ide-source-view-mode.h
index 6959f7e2e..a24565f89 100644
--- a/src/libide/sourceview/ide-source-view-mode.h
+++ b/src/libide/sourceview/ide-source-view-mode.h
@@ -1,6 +1,7 @@
 /* ide-source-view-mode.h
  *
  * Copyright 2015 Alexander Larsson <alexl redhat com>
+ * Copyright 2015-2019 Christian Hergert <chergert redhat com>
  *
  * 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
@@ -22,8 +23,7 @@
 
 #include <gtk/gtk.h>
 
-#include "ide-types.h"
-#include "sourceview/ide-source-view.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
@@ -45,9 +45,9 @@ void                   ide_source_view_mode_set_has_selection            (IdeSou
                                                                           gboolean               
has_selection);
 IdeSourceViewMode     *_ide_source_view_mode_new                         (GtkWidget             *view,
                                                                           const char            *mode,
-                                                                          IdeSourceViewModeType  type) 
G_GNUC_INTERNAL;
+                                                                          IdeSourceViewModeType  type);
 gboolean               _ide_source_view_mode_do_event                    (IdeSourceViewMode     *mode,
                                                                           GdkEventKey           *event,
-                                                                          gboolean              *remove) 
G_GNUC_INTERNAL;
+                                                                          gboolean              *remove);
 
 G_END_DECLS
diff --git a/src/libide/sourceview/ide-source-view-movements.c 
b/src/libide/sourceview/ide-source-view-movements.c
index 692575f64..6cbd44175 100644
--- a/src/libide/sourceview/ide-source-view-movements.c
+++ b/src/libide/sourceview/ide-source-view-movements.c
@@ -25,12 +25,11 @@
 #include <dazzle.h>
 #include <string.h>
 
-#include "ide-enums.h"
-#include "ide-debug.h"
+#include <libide-code.h>
 
-#include "sourceview/ide-source-iter.h"
-#include "sourceview/ide-source-view-movements.h"
-#include "sourceview/ide-text-iter.h"
+#include "ide-source-view-enums.h"
+#include "ide-source-view-movements.h"
+#include "ide-source-view-private.h"
 
 #define ANCHOR_BEGIN   "SELECTION_ANCHOR_BEGIN"
 #define ANCHOR_END     "SELECTION_ANCHOR_END"
@@ -1001,20 +1000,20 @@ match_char_with_depth (GtkTextIter      *iter,
       if (string_mode)
         {
           gtk_text_iter_set_line_offset (&limit, 0);
-          ret = _ide_text_iter_backward_find_char (iter, bracket_predicate, &state, &limit);
+          ret = ide_text_iter_backward_find_char (iter, bracket_predicate, &state, &limit);
         }
       else
-        ret = _ide_text_iter_backward_find_char (iter, bracket_predicate, &state, NULL);
+        ret = ide_text_iter_backward_find_char (iter, bracket_predicate, &state, NULL);
     }
   else
     {
       if (string_mode)
         {
           gtk_text_iter_forward_to_line_end (&limit);
-          ret = _ide_text_iter_forward_find_char (iter, bracket_predicate, &state, &limit);
+          ret = ide_text_iter_forward_find_char (iter, bracket_predicate, &state, &limit);
         }
       else
-        ret = _ide_text_iter_forward_find_char (iter, bracket_predicate, &state, NULL);
+        ret = ide_text_iter_forward_find_char (iter, bracket_predicate, &state, NULL);
     }
 
   if (ret && !is_exclusive)
@@ -1064,17 +1063,17 @@ macro_conditionals_qualify_iter (GtkTextIter *insert,
                                  GtkTextIter *cond_end,
                                  gboolean     include_str_bounds)
 {
-  if (_ide_text_iter_in_string (insert, "#ifdef", cond_start, cond_end, include_str_bounds))
+  if (ide_text_iter_in_string (insert, "#ifdef", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_IFDEF;
-  else if (_ide_text_iter_in_string (insert, "#ifndef", cond_start, cond_end, include_str_bounds))
+  else if (ide_text_iter_in_string (insert, "#ifndef", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_IFNDEF;
-  else if (_ide_text_iter_in_string (insert, "#if", cond_start, cond_end, include_str_bounds))
+  else if (ide_text_iter_in_string (insert, "#if", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_IF;
-  else if (_ide_text_iter_in_string (insert, "#elif", cond_start, cond_end, include_str_bounds))
+  else if (ide_text_iter_in_string (insert, "#elif", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_ELIF;
-  else if (_ide_text_iter_in_string (insert, "#else", cond_start, cond_end, include_str_bounds))
+  else if (ide_text_iter_in_string (insert, "#else", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_ELSE;
-  else if (_ide_text_iter_in_string (insert, "#endif", cond_start, cond_end, include_str_bounds))
+  else if (ide_text_iter_in_string (insert, "#endif", cond_start, cond_end, include_str_bounds))
     return MACRO_COND_ENDIF;
   else
     return MACRO_COND_NONE;
@@ -1290,7 +1289,7 @@ match_comments (GtkTextIter *insert,
 
   if (comment_start && !gtk_text_iter_is_end (&cursor))
     {
-      if (_ide_text_iter_find_chars_forward (&cursor, NULL, NULL, "*/", FALSE))
+      if (ide_text_iter_find_chars_forward (&cursor, NULL, NULL, "*/", FALSE))
         {
           gtk_text_iter_forward_char (&cursor);
           *insert = cursor;
@@ -1300,7 +1299,7 @@ match_comments (GtkTextIter *insert,
     }
   else if (!comment_start && !gtk_text_iter_is_start (&cursor))
     {
-      if (_ide_text_iter_find_chars_backward (&cursor, NULL, NULL, "/*", FALSE))
+      if (ide_text_iter_find_chars_backward (&cursor, NULL, NULL, "/*", FALSE))
         {
           *insert = cursor;
 
@@ -1347,7 +1346,7 @@ ide_source_view_movements_match_special (Movement *mv)
   if (!vim_percent_predicate (&mv->insert, start_char, NULL))
     {
 loop:
-      if (_ide_text_iter_forward_find_char (&mv->insert, vim_percent_predicate, NULL, &limit))
+      if (ide_text_iter_forward_find_char (&mv->insert, vim_percent_predicate, NULL, &limit))
         start_char = gtk_text_iter_get_char (&mv->insert);
       else
         {
@@ -1502,7 +1501,7 @@ ide_source_view_movements_next_word_end (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_forward_word_end (&mv->insert, mv->newline_stop);
+  ide_text_iter_forward_word_end (&mv->insert, mv->newline_stop);
 
   /* prefer an empty line before word */
   text_iter_forward_to_empty_line (&copy, &mv->insert);
@@ -1520,7 +1519,7 @@ ide_source_view_movements_next_full_word_end (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_forward_WORD_end (&mv->insert, mv->newline_stop);
+  ide_text_iter_forward_WORD_end (&mv->insert, mv->newline_stop);
 
   /* prefer an empty line before word */
   text_iter_forward_to_empty_line (&copy, &mv->insert);
@@ -1538,7 +1537,7 @@ ide_source_view_movements_next_word_start (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_forward_word_start (&mv->insert, mv->newline_stop);
+  ide_text_iter_forward_word_start (&mv->insert, mv->newline_stop);
 
   /* prefer an empty line before word */
   text_iter_forward_to_empty_line (&copy, &mv->insert);
@@ -1556,7 +1555,7 @@ ide_source_view_movements_next_full_word_start (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_forward_WORD_start (&mv->insert, mv->newline_stop);
+  ide_text_iter_forward_WORD_start (&mv->insert, mv->newline_stop);
 
   /* prefer an empty line before word */
   text_iter_forward_to_empty_line (&copy, &mv->insert);
@@ -1574,7 +1573,7 @@ ide_source_view_movements_previous_word_start (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_backward_word_start (&mv->insert, mv->newline_stop);
+  ide_text_iter_backward_word_start (&mv->insert, mv->newline_stop);
 
   /*
    * Vim treats an empty line as a word.
@@ -1594,7 +1593,7 @@ ide_source_view_movements_previous_full_word_start (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_backward_WORD_start (&mv->insert, mv->newline_stop);
+  ide_text_iter_backward_WORD_start (&mv->insert, mv->newline_stop);
 
   /*
    * Vim treats an empty line as a word.
@@ -1614,7 +1613,7 @@ ide_source_view_movements_previous_word_end (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_backward_word_end (&mv->insert, mv->newline_stop);
+  ide_text_iter_backward_word_end (&mv->insert, mv->newline_stop);
 
   /*
    * Vim treats an empty line as a word.
@@ -1638,7 +1637,7 @@ ide_source_view_movements_previous_full_word_end (Movement *mv)
 
   copy = mv->insert;
 
-  _ide_text_iter_backward_WORD_end (&mv->insert, mv->newline_stop);
+  ide_text_iter_backward_WORD_end (&mv->insert, mv->newline_stop);
 
   /*
    * Vim treats an empty line as a word.
@@ -1658,7 +1657,7 @@ ide_source_view_movements_previous_full_word_end (Movement *mv)
 static void
 ide_source_view_movements_paragraph_start (Movement *mv)
 {
-  _ide_text_iter_backward_paragraph_start (&mv->insert);
+  ide_text_iter_backward_paragraph_start (&mv->insert);
 
   if (mv->exclusive)
     {
@@ -1673,7 +1672,7 @@ ide_source_view_movements_paragraph_start (Movement *mv)
 static void
 ide_source_view_movements_paragraph_end (Movement *mv)
 {
-  _ide_text_iter_forward_paragraph_end (&mv->insert);
+  ide_text_iter_forward_paragraph_end (&mv->insert);
 
   if (mv->exclusive)
     {
@@ -1694,13 +1693,13 @@ ide_source_view_movements_paragraph_end (Movement *mv)
 static void
 ide_source_view_movements_sentence_start (Movement *mv)
 {
-  _ide_text_iter_backward_sentence_start (&mv->insert);
+  ide_text_iter_backward_sentence_start (&mv->insert);
 }
 
 static void
 ide_source_view_movements_sentence_end (Movement *mv)
 {
-  _ide_text_iter_forward_sentence_end (&mv->insert);
+  ide_text_iter_forward_sentence_end (&mv->insert);
 }
 
 static void
@@ -2554,10 +2553,10 @@ find_html_tag (GtkTextIter      *iter,
   g_return_val_if_fail (direction == GTK_DIR_LEFT || direction == GTK_DIR_RIGHT, NULL);
 
   if (direction == GTK_DIR_LEFT)
-    ret = _ide_text_iter_backward_find_char (iter, html_tag_predicate, GUINT_TO_POINTER ('<'), NULL);
+    ret = ide_text_iter_backward_find_char (iter, html_tag_predicate, GUINT_TO_POINTER ('<'), NULL);
   else
     ret = (gtk_text_iter_get_char (iter) == '<') ||
-          _ide_text_iter_forward_find_char (iter, html_tag_predicate, GUINT_TO_POINTER ('<'), NULL);
+          ide_text_iter_forward_find_char (iter, html_tag_predicate, GUINT_TO_POINTER ('<'), NULL);
 
   if (!ret)
     return NULL;
@@ -2592,11 +2591,11 @@ find_html_tag (GtkTextIter      *iter,
 
       return tag;
     }
-  else if (_ide_text_iter_find_chars_forward (&cursor, NULL, &end, "!--", TRUE))
+  else if (ide_text_iter_find_chars_forward (&cursor, NULL, &end, "!--", TRUE))
     {
       tag->kind = HTML_TAG_KIND_COMMENT;
       cursor = end;
-      if (_ide_text_iter_find_chars_forward (&cursor, NULL, &end, "-->", FALSE))
+      if (ide_text_iter_find_chars_forward (&cursor, NULL, &end, "-->", FALSE))
         {
           tag->end = end;
           if (direction == GTK_DIR_RIGHT)
@@ -2664,10 +2663,10 @@ static HtmlTag *
 find_non_matching_html_tag_at_left (GtkTextIter *cursor,
                                     gboolean     block_cursor)
 {
-  GQueue *stack;
-  HtmlTag *tag;
-  HtmlTag *last_closing_tag;
   GtkTextIter cursor_right;
+  HtmlTag *last_closing_tag = NULL;
+  HtmlTag *tag = NULL;
+  GQueue *stack = NULL;
 
   stack = g_queue_new ();
 
@@ -2766,10 +2765,11 @@ find_non_matching_html_tag_at_right (GtkTextIter *cursor,
       else if (tag->kind == HTML_TAG_KIND_ERROR)
         gtk_text_iter_forward_char (&cursor_left);
 
-      free_html_tag (tag);
+      g_clear_pointer (&tag, free_html_tag);
     }
 
   g_queue_free_full (stack, free_html_tag);
+  g_clear_pointer (&tag, free_html_tag);
 
   return tag;
 }
diff --git a/src/libide/sourceview/ide-source-view-movements.h 
b/src/libide/sourceview/ide-source-view-movements.h
index ad43fe735..bf51dbd2d 100644
--- a/src/libide/sourceview/ide-source-view-movements.h
+++ b/src/libide/sourceview/ide-source-view-movements.h
@@ -20,7 +20,7 @@
 
 #pragma once
 
-#include "sourceview/ide-source-view.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
@@ -34,14 +34,12 @@ void _ide_source_view_apply_movement (IdeSourceView         *source_view,
                                       gunichar               modifier,
                                       gunichar               search_char,
                                       guint                 *target_column);
-
 void _ide_source_view_select_inner   (IdeSourceView *self,
                                       gunichar       inner_left,
                                       gunichar       inner_right,
                                       gint           count,
                                       gboolean       exclusive,
                                       gboolean       string_mode);
-
 void _ide_source_view_select_tag     (IdeSourceView *self,
                                       gint           count,
                                       gboolean       exclusive);
diff --git a/src/libide/sourceview/ide-source-view-private.h b/src/libide/sourceview/ide-source-view-private.h
index a224f020b..6c9be3a64 100644
--- a/src/libide/sourceview/ide-source-view-private.h
+++ b/src/libide/sourceview/ide-source-view-private.h
@@ -20,10 +20,16 @@
 
 #pragma once
 
-#include "sourceview/ide-source-view.h"
+#include "ide-source-view.h"
 
 G_BEGIN_DECLS
 
-void _ide_source_view_init_shortcuts (IdeSourceView *self);
+void         _ide_source_view_init_shortcuts  (IdeSourceView *self);
+const gchar *_ide_source_view_get_mode_name   (IdeSourceView *self);
+void         _ide_source_view_set_count       (IdeSourceView *self,
+                                               gint           count);
+void         _ide_source_view_set_modifier    (IdeSourceView *self,
+                                               gunichar       modifier);
+GtkTextMark *_ide_source_view_get_scroll_mark (IdeSourceView *self);
 
 G_END_DECLS
diff --git a/src/libide/sourceview/ide-source-view-shortcuts.c 
b/src/libide/sourceview/ide-source-view-shortcuts.c
index 25be55e7b..f9224b17b 100644
--- a/src/libide/sourceview/ide-source-view-shortcuts.c
+++ b/src/libide/sourceview/ide-source-view-shortcuts.c
@@ -24,12 +24,8 @@
 
 #include <dazzle.h>
 
-#include "sourceview/ide-source-view.h"
-#include "sourceview/ide-source-view-private.h"
-
-/* static const DzlShortcutEntry source_view_shortcuts[] = { */
-/*   { NULL } */
-/* }; */
+#include "ide-source-view.h"
+#include "ide-source-view-private.h"
 
 void
 _ide_source_view_init_shortcuts (IdeSourceView *self)
@@ -45,9 +41,4 @@ _ide_source_view_init_shortcuts (IdeSourceView *self)
                                               "Escape",
                                               DZL_SHORTCUT_PHASE_BUBBLE,
                                               "reset", 0);
-
-  /* dzl_shortcut_manager_add_shortcut_entries (NULL, */
-  /*                                            source_view_shortcuts, */
-  /*                                            G_N_ELEMENTS (source_view_shortcuts), */
-  /*                                            GETTEXT_PACKAGE); */
 }
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index 7b88b4729..82e8eb347 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -25,51 +25,30 @@
 #include <cairo-gobject.h>
 #include <dazzle.h>
 #include <glib/gi18n.h>
+#include <libide-code.h>
+#include <libide-plugins.h>
+#include <libide-threading.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "ide-context.h"
-#include "ide-debug.h"
-#include "ide-enums.h"
-
-#include "application/ide-application.h"
-#include "buffers/ide-buffer-manager.h"
-#include "buffers/ide-buffer.h"
-#include "buffers/ide-buffer-private.h"
-#include "completion/ide-completion.h"
-#include "completion/ide-completion-private.h"
-#include "diagnostics/ide-diagnostic.h"
-#include "diagnostics/ide-fixit.h"
-#include "diagnostics/ide-source-location.h"
-#include "diagnostics/ide-source-range.h"
-#include "files/ide-file-settings.h"
-#include "files/ide-file.h"
-#include "hover/ide-hover-private.h"
-#include "plugins/ide-extension-adapter.h"
-#include "plugins/ide-extension-set-adapter.h"
-#include "rename/ide-rename-provider.h"
-#include "snippets/ide-snippet-chunk.h"
-#include "snippets/ide-snippet-context.h"
-#include "snippets/ide-snippet-private.h"
-#include "snippets/ide-snippet.h"
-#include "sourceview/ide-cursor.h"
-#include "sourceview/ide-indenter.h"
-#include "sourceview/ide-omni-gutter-renderer.h"
-#include "sourceview/ide-omni-gutter-renderer-private.h"
-#include "sourceview/ide-source-iter.h"
-#include "sourceview/ide-source-view-capture.h"
-#include "sourceview/ide-source-view-mode.h"
-#include "sourceview/ide-source-view-movements.h"
-#include "sourceview/ide-source-view-private.h"
-#include "sourceview/ide-source-view.h"
-#include "sourceview/ide-text-util.h"
-#include "symbols/ide-symbol.h"
-#include "symbols/ide-symbol-resolver.h"
-#include "util/ide-gtk.h"
-#include "vcs/ide-vcs.h"
-#include "workbench/ide-workbench-private.h"
-#include "threading/ide-task.h"
-#include "util/ide-glib.h"
+#include "ide-buffer-private.h"
+
+#include "ide-completion-private.h"
+#include "ide-completion.h"
+#include "ide-cursor.h"
+#include "ide-hover-private.h"
+#include "ide-indenter.h"
+#include "ide-snippet-chunk.h"
+#include "ide-snippet-context.h"
+#include "ide-snippet-private.h"
+#include "ide-snippet.h"
+#include "ide-source-view-capture.h"
+#include "ide-source-view-mode.h"
+#include "ide-source-view-movements.h"
+#include "ide-source-view-private.h"
+#include "ide-source-view.h"
+#include "ide-source-view-enums.h"
+#include "ide-text-util.h"
 
 #define INCLUDE_STATEMENTS "^#include[\\s]+[\\\"\\<][^\\s\\\"\\\'\\<\\>[:cntrl:]]+[\\\"\\>]"
 
@@ -114,7 +93,7 @@ typedef struct
   GQueue                      *snippets;
   DzlAnimation                *hadj_animation;
   DzlAnimation                *vadj_animation;
-  IdeOmniGutterRenderer       *omni_renderer;
+  IdeGutter                   *gutter;
 
   IdeCompletion               *completion;
   IdeHover                    *hover;
@@ -151,7 +130,7 @@ typedef struct
   guint                        delay_size_allocate_chainup;
   GtkAllocation                delay_size_allocation;
 
-  IdeSourceLocation           *definition_src_location;
+  IdeLocation                 *definition_src_location;
   GtkTextMark                 *definition_highlight_start_mark;
   GtkTextMark                 *definition_highlight_end_mark;
 
@@ -175,6 +154,9 @@ typedef struct
   guint                        snippet_completion : 1;
   guint                        waiting_for_capture : 1;
   guint                        waiting_for_symbol : 1;
+  guint                        show_line_changes : 1;
+  guint                        show_line_diagnostics : 1;
+  guint                        show_line_numbers : 1;
 } IdeSourceViewPrivate;
 
 typedef struct
@@ -187,7 +169,7 @@ typedef struct
 typedef struct
 {
   GPtrArray         *resolvers;
-  IdeSourceLocation *location;
+  IdeLocation *location;
 } FindReferencesTaskData;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeSourceView, ide_source_view, GTK_SOURCE_TYPE_VIEW)
@@ -302,22 +284,38 @@ static gdouble     fontScale [LAST_FONT_SCALE] = {
   1.2, 1.44, 1.728, 2.48832,
 };
 
-static void ide_source_view_real_save_insert_mark    (IdeSourceView         *self);
-static void ide_source_view_real_restore_insert_mark (IdeSourceView         *self);
-static void ide_source_view_real_set_mode            (IdeSourceView         *self,
-                                                      const gchar           *name,
-                                                      IdeSourceViewModeType  type);
-static void ide_source_view_save_column              (IdeSourceView         *self);
-static void ide_source_view_maybe_overwrite          (IdeSourceView         *self,
-                                                      GtkTextIter           *iter,
-                                                      const gchar           *text,
-                                                      gint                   len);
+static gboolean ide_source_view_do_size_allocate_hack_cb (gpointer               data);
+static void     ide_source_view_real_save_insert_mark    (IdeSourceView         *self);
+static void     ide_source_view_real_restore_insert_mark (IdeSourceView         *self);
+static void     ide_source_view_real_set_mode            (IdeSourceView         *self,
+                                                          const gchar           *name,
+                                                          IdeSourceViewModeType  type);
+static void     ide_source_view_save_column              (IdeSourceView         *self);
+static void     ide_source_view_maybe_overwrite          (IdeSourceView         *self,
+                                                          GtkTextIter           *iter,
+                                                          const gchar           *text,
+                                                          gint                   len);
+
+static gpointer
+get_selection_owner (IdeSourceView *self)
+{
+  return g_object_get_data (G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+                            "IDE_SOURCE_VIEW_SELECTION_OWNER");
+}
+
+static void
+set_selection_owner (IdeSourceView *self,
+                     gpointer       tag)
+{
+  g_object_set_data (G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+                     "IDE_SOURCE_VIEW_SELECTION_OWNER", tag);
+}
 
 static void
 find_references_task_data_free (FindReferencesTaskData *data)
 {
   g_clear_pointer (&data->resolvers, g_ptr_array_unref);
-  g_clear_pointer (&data->location, ide_source_location_unref);
+  g_clear_object (&data->location);
   g_slice_free (FindReferencesTaskData, data);
 }
 
@@ -364,21 +362,6 @@ ide_source_view_set_interactive_completion (IdeSourceView *self,
     }
 }
 
-static void
-find_references_task_get_extension (IdeExtensionSetAdapter *set,
-                                    PeasPluginInfo         *plugin_info,
-                                    PeasExtension          *extension,
-                                    gpointer                user_data)
-{
-  FindReferencesTaskData *data = user_data;
-  IdeSymbolResolver *resolver = (IdeSymbolResolver *)extension;
-
-  g_assert (data != NULL);
-  g_assert (IDE_IS_SYMBOL_RESOLVER (resolver));
-
-  g_ptr_array_add (data->resolvers, g_object_ref (resolver));
-}
-
 static void
 definition_highlight_data_free (DefinitionHighlightData *data)
 {
@@ -781,7 +764,7 @@ ide_source_view_set_file_settings (IdeSourceView   *self,
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (IDE_IS_FILE_SETTINGS (file_settings));
+  g_assert (!file_settings || IDE_IS_FILE_SETTINGS (file_settings));
 
   if (file_settings != ide_source_view_get_file_settings (self))
     {
@@ -791,80 +774,14 @@ ide_source_view_set_file_settings (IdeSourceView   *self,
 }
 
 static void
-ide_source_view__file_load_settings_cb (GObject      *object,
-                                        GAsyncResult *result,
-                                        gpointer      user_data)
-{
-  g_autoptr(IdeSourceView) self = user_data;
-  g_autoptr(IdeFileSettings) file_settings = NULL;
-  g_autoptr(GError) error = NULL;
-  IdeFile *file = (IdeFile *)object;
-
-  g_assert (IDE_IS_FILE (file));
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-
-  file_settings = ide_file_load_settings_finish (file, result, &error);
-
-  if (!file_settings)
-    {
-      g_message ("%s", error->message);
-      return;
-    }
-
-  ide_source_view_set_file_settings (self, file_settings);
-}
-
-static void
-ide_source_view_reload_file_settings (IdeSourceView *self)
-{
-  IdeBuffer *buffer;
-  IdeFile *file;
-
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (IDE_IS_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (self))));
-
-  buffer = IDE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (self)));
-  file = ide_buffer_get_file (buffer);
-
-  ide_file_load_settings_async (file,
-                                NULL,
-                                ide_source_view__file_load_settings_cb,
-                                g_object_ref (self));
-}
-
-static void
-ide_source_view_reload_language (IdeSourceView *self)
-{
-  GtkSourceLanguage *language;
-  GtkTextBuffer *buffer;
-  IdeFile *file = NULL;
-
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-
-  /*
-   * Update source language, etc.
-   */
-  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
-  file = ide_buffer_get_file (IDE_BUFFER (buffer));
-  language = ide_file_get_language (file);
-
-  g_assert (IDE_IS_BUFFER (buffer));
-  g_assert (IDE_IS_FILE (file));
-  g_assert (!language || GTK_SOURCE_IS_LANGUAGE (language));
-
-  gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer), language);
-}
-
-static void
-ide_source_view__buffer_notify_file_cb (IdeSourceView *self,
-                                        GParamSpec    *pspec,
-                                        IdeBuffer     *buffer)
+ide_source_view__buffer_notify_file_settings_cb (IdeSourceView *self,
+                                                 GParamSpec    *pspec,
+                                                 IdeBuffer     *buffer)
 {
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_BUFFER (buffer));
 
-  ide_source_view_reload_language (self);
-  ide_source_view_reload_file_settings (self);
+  ide_source_view_set_file_settings (self, ide_buffer_get_file_settings (buffer));
 }
 
 static void
@@ -963,8 +880,8 @@ ide_source_view_rebuild_css (IdeSourceView *self)
       css = g_strdup_printf ("textview { %s }", str ?: "");
       gtk_css_provider_load_from_data (priv->css_provider, css, -1, NULL);
 
-      if (priv->omni_renderer != NULL)
-        _ide_omni_gutter_renderer_reset_font (priv->omni_renderer);
+      if (priv->gutter != NULL)
+        ide_gutter_style_changed (priv->gutter);
 
       if (priv->completion != NULL)
         _ide_completion_set_font_description (priv->completion, font_desc);
@@ -1190,31 +1107,29 @@ ide_source_view__buffer_notify_has_selection_cb (IdeSourceView *self,
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   gboolean has_selection;
-  IdeWorkbench *workbench = ide_widget_get_workbench (GTK_WIDGET (self));
 
   has_selection = gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (buffer));
   ide_source_view_mode_set_has_selection (priv->mode, has_selection);
 
-  if (workbench == NULL)
-    return;
-
   if (has_selection)
-    ide_workbench_set_selection_owner (workbench, G_OBJECT (self));
-  else if (ide_workbench_get_selection_owner (workbench) == G_OBJECT (self))
-    ide_workbench_set_selection_owner (workbench, NULL);
+    set_selection_owner (self, G_OBJECT (self));
+  else if (get_selection_owner (self) == G_OBJECT (self))
+    set_selection_owner (self, NULL);
 }
 
 static void
 ide_source_view__buffer_line_flags_changed_cb (IdeSourceView *self,
                                                IdeBuffer     *buffer)
 {
+  GtkSourceGutter *gutter;
+
   IDE_ENTRY;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_BUFFER (buffer));
 
-  gtk_source_gutter_queue_draw (gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self),
-                                                            GTK_TEXT_WINDOW_LEFT));
+  gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
+  gtk_source_gutter_queue_draw (gutter);
 
   IDE_EXIT;
 }
@@ -1280,7 +1195,7 @@ ide_source_view_reset_definition_highlight (IdeSourceView *self)
   g_assert (IDE_IS_SOURCE_VIEW (self));
 
   if (priv->definition_src_location)
-    g_clear_pointer (&priv->definition_src_location, ide_source_location_unref);
+    g_clear_object (&priv->definition_src_location);
 
   if (priv->buffer != NULL)
     {
@@ -1338,12 +1253,14 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
                              DzlSignalGroup *group)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+  g_autoptr(IdeContext) context = NULL;
   GtkTextMark *insert;
+  IdeObjectBox *box;
   GtkTextIter iter;
-  IdeContext *context;
 
   IDE_ENTRY;
 
+  g_assert (IDE_IS_MAIN_THREAD ());
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_BUFFER (buffer));
   g_assert (DZL_IS_SIGNAL_GROUP (group));
@@ -1360,11 +1277,13 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
       priv->completion_blocked = TRUE;
     }
 
-  context = ide_buffer_get_context (buffer);
+  context = ide_buffer_ref_context (buffer);
 
   _ide_hover_set_context (priv->hover, context);
 
-  priv->indenter_adapter = ide_extension_adapter_new (context,
+  box = ide_object_box_from_object (G_OBJECT (buffer));
+
+  priv->indenter_adapter = ide_extension_adapter_new (IDE_OBJECT (box),
                                                       peas_engine_get_default (),
                                                       IDE_TYPE_INDENTER,
                                                       "Indenter-Languages",
@@ -1388,7 +1307,7 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
   g_object_ref (priv->definition_highlight_end_mark);
 
   ide_source_view__buffer_notify_language_cb (self, NULL, buffer);
-  ide_source_view__buffer_notify_file_cb (self, NULL, buffer);
+  ide_source_view__buffer_notify_file_settings_cb (self, NULL, buffer);
   ide_source_view__buffer_notify_style_scheme_cb (self, NULL, buffer);
   ide_source_view__buffer__notify_can_redo (self, NULL, buffer);
   ide_source_view__buffer__notify_can_undo (self, NULL, buffer);
@@ -1428,7 +1347,7 @@ ide_source_view_unbind_buffer (IdeSourceView  *self,
       g_clear_object (&priv->cursor);
     }
 
-  g_clear_object (&priv->indenter_adapter);
+  ide_clear_and_destroy_object (&priv->indenter_adapter);
   g_clear_object (&priv->definition_highlight_start_mark);
   g_clear_object (&priv->definition_highlight_end_mark);
 
@@ -2299,9 +2218,9 @@ ide_source_view_process_press_on_definition (IdeSourceView  *self,
 
       if (gtk_text_iter_in_range (&iter, &definition_highlight_start, &definition_highlight_end))
         {
-          g_autoptr(IdeSourceLocation) src_location = NULL;
+          g_autoptr(IdeLocation) src_location = NULL;
 
-          src_location = ide_source_location_ref (priv->definition_src_location);
+          src_location = g_object_ref (priv->definition_src_location);
           ide_source_view_reset_definition_highlight (self);
           g_signal_emit (self, signals [FOCUS_LOCATION], 0, src_location);
         }
@@ -2447,7 +2366,7 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject      *object,
   IdeBuffer *buffer = (IdeBuffer *)object;
   g_autoptr(IdeSymbol) symbol = NULL;
   g_autoptr(GError) error = NULL;
-  IdeSourceLocation *srcloc;
+  IdeLocation *srcloc;
   IdeSymbolKind kind;
 
   IDE_ENTRY;
@@ -2475,10 +2394,10 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject      *object,
 
   kind = ide_symbol_get_kind (symbol);
 
-  srcloc = ide_symbol_get_definition_location (symbol);
+  srcloc = ide_symbol_get_location (symbol);
 
   if (srcloc == NULL)
-    srcloc = ide_symbol_get_declaration_location (symbol);
+    srcloc = ide_symbol_get_header_location (symbol);
 
   if (srcloc != NULL)
     {
@@ -2486,17 +2405,17 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject      *object,
       GtkTextIter word_end;
 
       if (priv->definition_src_location != NULL && priv->definition_src_location != srcloc)
-        g_clear_pointer (&priv->definition_src_location, ide_source_location_unref);
+        g_clear_object (&priv->definition_src_location);
 
       if (priv->definition_src_location == NULL)
-        priv->definition_src_location = ide_source_location_ref (srcloc);
+        priv->definition_src_location = g_object_ref (srcloc);
 
       gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer),
                                         &word_start, data->word_start_mark);
       gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer),
                                         &word_end, data->word_end_mark);
 
-      if (kind == IDE_SYMBOL_HEADER)
+      if (kind == IDE_SYMBOL_KIND_HEADER)
         {
           GtkTextIter line_start = word_start;
           GtkTextIter line_end = word_end;
@@ -3387,8 +3306,10 @@ ide_source_view_real_move_error (IdeSourceView    *self,
                                  GtkDirectionType  dir)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+  IdeDiagnostics *diagnostics;
   GtkTextBuffer *buffer;
   GtkTextMark *insert;
+  GFile *file;
   GtkTextIter iter;
   gboolean wrap_around = TRUE;
   gboolean (*movement) (GtkTextIter *) = NULL;
@@ -3398,6 +3319,11 @@ ide_source_view_real_move_error (IdeSourceView    *self,
   if (!priv->buffer)
     return;
 
+  if (!(diagnostics = ide_buffer_get_diagnostics (priv->buffer)))
+    return;
+
+  file = ide_buffer_get_file (priv->buffer);
+
   if (dir == GTK_DIR_RIGHT)
     dir = GTK_DIR_DOWN;
   else if (dir == GTK_DIR_LEFT)
@@ -3424,12 +3350,11 @@ wrapped:
   while (movement (&iter))
     {
       IdeDiagnostic *diag;
+      guint line = gtk_text_iter_get_line (&iter);
 
-      diag = ide_buffer_get_diagnostic_at_iter (priv->buffer, &iter);
-
-      if (diag)
+      if ((diag = ide_diagnostics_get_diagnostic_at_line (diagnostics, file, line)))
         {
-          IdeSourceLocation *location;
+          IdeLocation *location;
 
           location = ide_diagnostic_get_location (diag);
 
@@ -3437,7 +3362,7 @@ wrapped:
             {
               guint line_offset;
 
-              line_offset = ide_source_location_get_line_offset (location);
+              line_offset = ide_location_get_line_offset (location);
               gtk_text_iter_set_line_offset (&iter, 0);
               for (; line_offset; line_offset--)
                 if (gtk_text_iter_ends_line (&iter) || !gtk_text_iter_forward_char (&iter))
@@ -3698,17 +3623,15 @@ ide_source_view_real_push_selection (IdeSourceView *self)
 }
 
 static void
-ide_source_view_real_push_snippet (IdeSourceView           *self,
+ide_source_view_real_push_snippet (IdeSourceView     *self,
                                    IdeSnippet        *snippet,
-                                   const GtkTextIter       *location)
+                                   const GtkTextIter *location)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeContext *ide_context;
-  IdeSnippetContext *context;
-  IdeFile *file;
-  GFile *gfile = NULL;
   g_autoptr(GFile) gparentfile = NULL;
-
+  g_autoptr(IdeContext) ide_context = NULL;
+  IdeSnippetContext *context;
+  GFile *file = NULL;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_SNIPPET (snippet));
@@ -3718,34 +3641,30 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
 
   if (priv->buffer != NULL)
     {
-      if ((file = ide_buffer_get_file (priv->buffer)) &&
-          (gfile = ide_file_get_file (file)))
+      if ((file = ide_buffer_get_file (priv->buffer)))
         {
           g_autofree gchar *name = NULL;
           g_autofree gchar *path = NULL;
           g_autofree gchar *dirname = NULL;
 
-          name = g_file_get_basename (gfile);
-          gparentfile = g_file_get_parent(gfile);
+          name = g_file_get_basename (file);
+          gparentfile = g_file_get_parent (file);
           dirname = g_file_get_path (gparentfile);
-          path = g_file_get_path (gfile);
+          path = g_file_get_path (file);
           ide_snippet_context_add_variable (context, "filename", name);
           ide_snippet_context_add_variable (context, "dirname", dirname);
           ide_snippet_context_add_variable (context, "path", path);
         }
 
-      if ((ide_context = ide_buffer_get_context (priv->buffer)))
+      if ((ide_context = ide_buffer_ref_context (priv->buffer)))
         {
-          IdeVcs *vcs;
-          IdeVcsConfig *vcs_config;
-          GFile *workdir;
+          g_autoptr(GFile) workdir = NULL;
 
-          vcs = ide_context_get_vcs (ide_context);
-          workdir = ide_vcs_get_working_directory (vcs);
-          if (workdir && gfile)
+          workdir = ide_context_ref_workdir (ide_context);
+          if (workdir && file)
             {
               g_autofree gchar *relative_path = NULL;
-              relative_path = g_file_get_relative_path (workdir, gfile);
+              relative_path = g_file_get_relative_path (workdir, file);
               ide_snippet_context_add_variable (context, "relative_path", relative_path);
             }
           if (workdir && gparentfile)
@@ -3754,32 +3673,6 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
               relative_dirname = g_file_get_relative_path (workdir, gparentfile);
               ide_snippet_context_add_variable (context, "relative_dirname", relative_dirname);
             }
-
-          if ((vcs_config = ide_vcs_get_config (vcs)))
-            {
-              GValue value = G_VALUE_INIT;
-
-              g_value_init (&value, G_TYPE_STRING);
-
-              ide_vcs_config_get_config (vcs_config, IDE_VCS_CONFIG_FULL_NAME, &value);
-
-              if (!dzl_str_empty0 (g_value_get_string (&value)))
-                {
-                  ide_snippet_context_add_shared_variable (context, "author", g_value_get_string (&value));
-                  ide_snippet_context_add_shared_variable (context, "fullname", g_value_get_string (&value));
-                  ide_snippet_context_add_shared_variable (context, "username", g_value_get_string (&value));
-                }
-
-              g_value_reset (&value);
-
-              ide_vcs_config_get_config (vcs_config, IDE_VCS_CONFIG_EMAIL, &value);
-
-              if (!dzl_str_empty0 (g_value_get_string (&value)))
-                ide_snippet_context_add_shared_variable (context, "email", g_value_get_string (&value));
-
-              g_value_unset (&value);
-              g_object_unref (vcs_config);
-            }
         }
     }
 }
@@ -3911,7 +3804,6 @@ ide_source_view_constructed (GObject *object)
 {
   IdeSourceView *self = (IdeSourceView *)object;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceGutter *gutter;
 
   G_OBJECT_CLASS (ide_source_view_parent_class)->constructed (object);
 
@@ -3922,13 +3814,6 @@ ide_source_view_constructed (GObject *object)
   priv->definition_src_location = NULL;
   ide_source_view_reset_definition_highlight (self);
 
-  gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
-  priv->omni_renderer = g_object_new (IDE_TYPE_OMNI_GUTTER_RENDERER,
-                                      "visible", TRUE,
-                                      NULL);
-  g_object_ref_sink (priv->omni_renderer);
-  gtk_source_gutter_insert (gutter, GTK_SOURCE_GUTTER_RENDERER (priv->omni_renderer), 0);
-
   priv->completion = _ide_completion_new (GTK_SOURCE_VIEW (self));
 
   /* Disable sourceview completion always */
@@ -4098,7 +3983,6 @@ ide_source_view_focus_in_event (GtkWidget     *widget,
 {
   IdeSourceView *self = (IdeSourceView *)widget;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeWorkbench *workbench;
   gboolean ret;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
@@ -4106,13 +3990,19 @@ ide_source_view_focus_in_event (GtkWidget     *widget,
   /* Restore the completion window now that we have regained focus. */
   unblock_interactive (self);
 
+  /* Force size allocation immediately if we have something queued. */
+  if (priv->delay_size_allocate_chainup)
+    {
+      g_source_remove (priv->delay_size_allocate_chainup);
+      ide_source_view_do_size_allocate_hack_cb (self);
+    }
+
   /*
    * Restore the insert mark, but ignore selections (since we cant ensure they
    * will stay looking selected, as the other frame could be a view into our
    * own buffer).
    */
-  workbench = ide_widget_get_workbench (GTK_WIDGET (widget));
-  if (!workbench || ide_workbench_get_selection_owner (workbench) != G_OBJECT (self))
+  if (get_selection_owner (self) != self)
     {
       priv->saved_selection_line = priv->saved_line;
       priv->saved_selection_line_column = priv->saved_line_column;
@@ -4221,7 +4111,7 @@ ide_source_view_goto_definition_symbol_cb (GObject      *object,
   g_autoptr(IdeSymbol) symbol = NULL;
   IdeBuffer *buffer = (IdeBuffer *)object;
   g_autoptr(GError) error = NULL;
-  IdeSourceLocation *srcloc;
+  IdeLocation *srcloc;
 
   IDE_ENTRY;
 
@@ -4236,20 +4126,20 @@ ide_source_view_goto_definition_symbol_cb (GObject      *object,
       IDE_EXIT;
     }
 
-  srcloc = ide_symbol_get_definition_location (symbol);
+  srcloc = ide_symbol_get_location (symbol);
 
   if (srcloc == NULL)
-    srcloc = ide_symbol_get_declaration_location (symbol);
+    srcloc = ide_symbol_get_header_location (symbol);
 
   if (srcloc != NULL)
     {
-      guint line = ide_source_location_get_line (srcloc);
-      guint line_offset = ide_source_location_get_line_offset (srcloc);
-      IdeFile *file = ide_source_location_get_file (srcloc);
-      IdeFile *our_file = ide_buffer_get_file (buffer);
+      guint line = ide_location_get_line (srcloc);
+      guint line_offset = ide_location_get_line_offset (srcloc);
+      GFile *file = ide_location_get_file (srcloc);
+      GFile *our_file = ide_buffer_get_file (buffer);
 
 #ifdef IDE_ENABLE_TRACE
-      const gchar *filename = ide_file_get_path (file);
+      const gchar *filename = g_file_peek_path (file);
 
       IDE_TRACE_MSG ("%s => %s +%u:%u",
                      ide_symbol_get_name (symbol),
@@ -4263,7 +4153,7 @@ ide_source_view_goto_definition_symbol_cb (GObject      *object,
        * If we are navigating within this file, just stay captive instead of
        * potentially allowing jumping to the file in another editor.
        */
-      if (ide_file_equal (file, our_file))
+      if (g_file_equal (file, our_file))
         {
           GtkTextIter iter;
 
@@ -4396,11 +4286,11 @@ ide_source_view_get_overwrite (IdeSourceView *self)
 
 static gchar *
 ide_source_view_get_fixit_label (IdeSourceView *self,
-                                 IdeFixit      *fixit)
+                                 IdeTextEdit      *fixit)
 {
-  IdeSourceLocation *begin_loc;
-  IdeSourceLocation *end_loc;
-  IdeSourceRange *range;
+  IdeLocation *begin_loc;
+  IdeLocation *end_loc;
+  IdeRange *range;
   GtkTextBuffer *buffer;
   GtkTextIter begin;
   GtkTextIter end;
@@ -4412,11 +4302,11 @@ ide_source_view_get_fixit_label (IdeSourceView *self,
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (fixit != NULL);
 
-  range = ide_fixit_get_range (fixit);
+  range = ide_text_edit_get_range (fixit);
   if (range == NULL)
     goto cleanup;
 
-  new_text = g_strdup (ide_fixit_get_text (fixit));
+  new_text = g_strdup (ide_text_edit_get_text (fixit));
   if (new_text == NULL)
     goto cleanup;
 
@@ -4424,11 +4314,11 @@ ide_source_view_get_fixit_label (IdeSourceView *self,
   if (!IDE_IS_BUFFER (buffer))
     goto cleanup;
 
-  begin_loc = ide_source_range_get_begin (range);
-  end_loc = ide_source_range_get_end (range);
+  begin_loc = ide_range_get_begin (range);
+  end_loc = ide_range_get_end (range);
 
-  ide_buffer_get_iter_at_source_location (IDE_BUFFER (buffer), &begin, begin_loc);
-  ide_buffer_get_iter_at_source_location (IDE_BUFFER (buffer), &end, end_loc);
+  ide_buffer_get_iter_at_location (IDE_BUFFER (buffer), &begin, begin_loc);
+  ide_buffer_get_iter_at_location (IDE_BUFFER (buffer), &end, end_loc);
 
   old_text = gtk_text_iter_get_slice (&begin, &end);
 
@@ -4470,7 +4360,7 @@ static void
 ide_source_view__fixit_activate (IdeSourceView *self,
                                  GtkMenuItem   *menu_item)
 {
-  IdeFixit *fixit;
+  IdeTextEdit *fixit;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (GTK_IS_MENU_ITEM (menu_item));
@@ -4479,8 +4369,8 @@ ide_source_view__fixit_activate (IdeSourceView *self,
 
   if (fixit != NULL)
     {
-      IdeSourceLocation *srcloc;
-      IdeSourceRange *range;
+      IdeLocation *srcloc;
+      IdeRange *range;
       GtkTextBuffer *buffer;
       const gchar *text;
       GtkTextIter begin;
@@ -4490,14 +4380,14 @@ ide_source_view__fixit_activate (IdeSourceView *self,
       if (!IDE_IS_BUFFER (buffer))
         return;
 
-      text = ide_fixit_get_text (fixit);
-      range = ide_fixit_get_range (fixit);
+      text = ide_text_edit_get_text (fixit);
+      range = ide_text_edit_get_range (fixit);
 
-      srcloc = ide_source_range_get_begin (range);
-      ide_buffer_get_iter_at_source_location (IDE_BUFFER (buffer), &begin, srcloc);
+      srcloc = ide_range_get_begin (range);
+      ide_buffer_get_iter_at_location (IDE_BUFFER (buffer), &begin, srcloc);
 
-      srcloc = ide_source_range_get_end (range);
-      ide_buffer_get_iter_at_source_location (IDE_BUFFER (buffer), &end, srcloc);
+      srcloc = ide_range_get_end (range);
+      ide_buffer_get_iter_at_location (IDE_BUFFER (buffer), &end, srcloc);
 
       gtk_text_buffer_begin_user_action (buffer);
       gtk_text_buffer_delete (buffer, &begin, &end);
@@ -4512,13 +4402,14 @@ ide_source_view_real_populate_popup (GtkTextView *text_view,
 {
   IdeSourceView *self = (IdeSourceView *)text_view;
   GtkSeparatorMenuItem *sep;
+  IdeDiagnostics *diagnostics;
+  IdeDiagnostic *diagnostic = NULL;
   GtkTextBuffer *buffer;
   GtkMenuItem *menu_item;
   GtkTextMark *insert;
   GtkTextIter iter;
   GtkTextIter begin;
   GtkTextIter end;
-  IdeDiagnostic *diagnostic;
   GMenu *model;
 
   g_assert (GTK_IS_TEXT_VIEW (text_view));
@@ -4547,15 +4438,18 @@ ide_source_view_real_populate_popup (GtkTextView *text_view,
 
   /*
    * Check if we have a diagnostic at this position and if there are fixits associated with it.
-   * If so, display the "Apply Fixit" menu item with available fixits.
+   * If so, display the "Apply TextEdit" menu item with available fixits.
    */
-  diagnostic = ide_buffer_get_diagnostic_at_iter (IDE_BUFFER (buffer), &iter);
+  if ((diagnostics = ide_buffer_get_diagnostics (IDE_BUFFER (buffer))))
+    diagnostic = ide_diagnostics_get_diagnostic_at_line (diagnostics,
+                                                         ide_buffer_get_file (IDE_BUFFER (buffer)),
+                                                         gtk_text_iter_get_line (&iter));
 
   if (diagnostic != NULL)
     {
       guint num_fixits;
 
-      num_fixits = ide_diagnostic_get_num_fixits (diagnostic);
+      num_fixits = ide_diagnostic_get_n_fixits (diagnostic);
 
       if (num_fixits > 0)
         {
@@ -4579,7 +4473,7 @@ ide_source_view_real_populate_popup (GtkTextView *text_view,
 
           for (i = 0; i < num_fixits; i++)
             {
-              IdeFixit *fixit;
+              IdeTextEdit *fixit;
               gchar *label;
 
               fixit = ide_diagnostic_get_fixit (diagnostic, i);
@@ -4593,8 +4487,8 @@ ide_source_view_real_populate_popup (GtkTextView *text_view,
 
               g_object_set_data_full (G_OBJECT (menu_item),
                                       "IDE_FIXIT",
-                                      ide_fixit_ref (fixit),
-                                      (GDestroyNotify)ide_fixit_unref);
+                                      g_object_ref (fixit),
+                                      (GDestroyNotify)g_object_unref);
 
               g_signal_connect_object (menu_item,
                                        "activate",
@@ -4889,8 +4783,8 @@ ide_source_view_rename_edits_cb (GObject      *object,
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   g_autoptr(GPtrArray) edits = NULL;
   g_autoptr(GError) error = NULL;
+  g_autoptr(IdeContext) context = NULL;
   IdeBufferManager *buffer_manager;
-  IdeContext *context;
 
   IDE_ENTRY;
 
@@ -4909,8 +4803,8 @@ ide_source_view_rename_edits_cb (GObject      *object,
 
   IDE_PTR_ARRAY_SET_FREE_FUNC (edits, g_object_unref);
 
-  context = ide_buffer_get_context (priv->buffer);
-  buffer_manager = ide_context_get_buffer_manager (context);
+  context = ide_buffer_ref_context (priv->buffer);
+  buffer_manager = ide_buffer_manager_from_context (context);
 
   ide_buffer_manager_apply_edits_async (buffer_manager,
                                         IDE_PTR_ARRAY_STEAL_FULL (&edits),
@@ -4927,7 +4821,7 @@ ide_source_view_rename_activate (IdeSourceView    *self,
                                  DzlSimplePopover *popover)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  g_autoptr(IdeSourceLocation) location = NULL;
+  g_autoptr(IdeLocation) location = NULL;
   IdeRenameProvider *provider;
 
   IDE_ENTRY;
@@ -4963,7 +4857,7 @@ ide_source_view_real_begin_rename (IdeSourceView *self)
 {
   IdeRenameProvider *provider;
   DzlSimplePopover *popover;
-  g_autofree gchar *uri = NULL;
+  g_autofree gchar *title = NULL;
   GtkTextBuffer *buffer;
   GtkTextMark *insert;
   GtkTextIter iter;
@@ -4983,14 +4877,14 @@ ide_source_view_real_begin_rename (IdeSourceView *self)
     }
 
   insert = gtk_text_buffer_get_insert (buffer);
-  uri = ide_buffer_get_uri (IDE_BUFFER (buffer));
+  title = ide_buffer_dup_title (IDE_BUFFER (buffer));
 
   gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
 
-  IDE_TRACE_MSG ("Renaming symbol found at %s: %d:%d",
-                 uri,
-                 gtk_text_iter_get_line (&iter) + 1,
-                 gtk_text_iter_get_line_offset (&iter) + 1);
+  g_debug ("Renaming symbol from %s +%d:%d",
+           title,
+           gtk_text_iter_get_line (&iter) + 1,
+           gtk_text_iter_get_line_offset (&iter) + 1);
 
   gtk_text_buffer_select_range (buffer, &iter, &iter);
   gtk_text_view_get_iter_location (GTK_TEXT_VIEW (self), &iter, &loc);
@@ -5078,7 +4972,7 @@ ide_source_view_real_find_references_jump (IdeSourceView *self,
                                            GtkListBoxRow *row,
                                            GtkListBox    *list_box)
 {
-  IdeSourceLocation *location;
+  IdeLocation *location;
 
   IDE_ENTRY;
 
@@ -5086,7 +4980,7 @@ ide_source_view_real_find_references_jump (IdeSourceView *self,
   g_assert (GTK_IS_LIST_BOX_ROW (row));
   g_assert (GTK_IS_LIST_BOX (list_box));
 
-  location = g_object_get_data (G_OBJECT (row), "IDE_SOURCE_LOCATION");
+  location = g_object_get_data (G_OBJECT (row), "IDE_LOCATION");
 
   if (location != NULL)
     g_signal_emit (self, signals [FOCUS_LOCATION], 0, location);
@@ -5096,11 +4990,11 @@ ide_source_view_real_find_references_jump (IdeSourceView *self,
 
 static gboolean
 insert_mark_within_range (IdeBuffer      *buffer,
-                          IdeSourceRange *range)
+                          IdeRange *range)
 {
   GtkTextMark *insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (buffer));
-  IdeSourceLocation *begin = ide_source_range_get_begin (range);
-  IdeSourceLocation *end = ide_source_range_get_end (range);
+  IdeLocation *begin = ide_range_get_begin (range);
+  IdeLocation *end = ide_range_get_end (range);
   GtkTextIter iter;
   GtkTextIter begin_iter;
   GtkTextIter end_iter;
@@ -5109,8 +5003,8 @@ insert_mark_within_range (IdeBuffer      *buffer,
     return FALSE;
 
   gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, insert);
-  ide_buffer_get_iter_at_source_location (buffer, &begin_iter, begin);
-  ide_buffer_get_iter_at_source_location (buffer, &end_iter, end);
+  ide_buffer_get_iter_at_location (buffer, &begin_iter, begin);
+  ide_buffer_get_iter_at_location (buffer, &end_iter, end);
 
   return gtk_text_iter_compare (&begin_iter, &iter) <= 0 &&
          gtk_text_iter_compare (&end_iter, &iter) >= 0;
@@ -5144,7 +5038,7 @@ ide_source_view_find_references_cb (GObject      *object,
 
   references = ide_symbol_resolver_find_references_finish (symbol_resolver, result, &error);
 
-  IDE_PTR_ARRAY_SET_FREE_FUNC (references, ide_source_range_unref);
+  IDE_PTR_ARRAY_SET_FREE_FUNC (references, g_object_unref);
 
   self = ide_task_get_source_object (task);
   priv = ide_source_view_get_instance_private (self);
@@ -5168,6 +5062,7 @@ ide_source_view_find_references_cb (GObject      *object,
 
       ide_symbol_resolver_find_references_async (resolver,
                                                  data->location,
+                                                 ide_buffer_get_language_id (priv->buffer),
                                                  cancellable,
                                                  ide_source_view_find_references_cb,
                                                  g_steal_pointer (&task));
@@ -5210,29 +5105,27 @@ ide_source_view_find_references_cb (GObject      *object,
 
   if (references != NULL && references->len > 0)
     {
-      IdeContext *context = ide_buffer_get_context (priv->buffer);
-      IdeVcs *vcs = ide_context_get_vcs (context);
-      GFile *workdir = ide_vcs_get_working_directory (vcs);
+      g_autoptr(IdeContext) context = ide_buffer_ref_context (priv->buffer);
+      g_autoptr(GFile) workdir = ide_context_ref_workdir (context);
 
       for (guint i = 0; i < references->len; i++)
         {
-          IdeSourceRange *range = g_ptr_array_index (references, i);
-          IdeSourceLocation *begin = ide_source_range_get_begin (range);
-          IdeFile *file = ide_source_location_get_file (begin);
-          GFile *gfile = ide_file_get_file (file);
-          guint line = ide_source_location_get_line (begin);
-          guint line_offset = ide_source_location_get_line_offset (begin);
+          IdeRange *range = g_ptr_array_index (references, i);
+          IdeLocation *begin = ide_range_get_begin (range);
+          GFile *file = ide_location_get_file (begin);
+          guint line = ide_location_get_line (begin);
+          guint line_offset = ide_location_get_line_offset (begin);
           g_autofree gchar *name = NULL;
           g_autofree gchar *text = NULL;
           GtkListBoxRow *row;
           GtkLabel *label;
 
-          if (g_file_has_prefix (gfile, workdir))
-            name = g_file_get_relative_path (workdir, gfile);
-          else if (g_file_is_native (gfile))
-            name = g_file_get_path (gfile);
+          if (g_file_has_prefix (file, workdir))
+            name = g_file_get_relative_path (workdir, file);
+          else if (g_file_is_native (file))
+            name = g_file_get_path (file);
           else
-            name = g_file_get_uri (gfile);
+            name = g_file_get_uri (file);
 
           /* translators: %s is the filename, then line number, column number. <> are pango markup */
           text = g_strdup_printf (_("<b>%s</b> — <small>Line %u, Column %u</small>"),
@@ -5249,9 +5142,9 @@ ide_source_view_find_references_cb (GObject      *object,
                               "visible", TRUE,
                               NULL);
           g_object_set_data_full (G_OBJECT (row),
-                                  "IDE_SOURCE_LOCATION",
-                                  ide_source_location_ref (begin),
-                                  (GDestroyNotify)ide_source_location_unref);
+                                  "IDE_LOCATION",
+                                  g_object_ref (begin),
+                                  g_object_unref);
           gtk_container_add (GTK_CONTAINER (list_box), GTK_WIDGET (row));
 
           if (insert_mark_within_range (priv->buffer, range))
@@ -5287,9 +5180,8 @@ ide_source_view_real_find_references (IdeSourceView *self)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   g_autoptr(IdeTask) task = NULL;
-  IdeExtensionSetAdapter *adapter;
+  g_autoptr(GPtrArray) resolvers = NULL;
   FindReferencesTaskData *data;
-  guint n_extensions;
   IdeSymbolResolver *resolver;
 
   IDE_ENTRY;
@@ -5299,29 +5191,26 @@ ide_source_view_real_find_references (IdeSourceView *self)
   task = ide_task_new (self, NULL, NULL, NULL);
   ide_task_set_source_tag (task, ide_source_view_real_find_references);
 
-  adapter = ide_buffer_get_symbol_resolvers (priv->buffer);
-  n_extensions = ide_extension_set_adapter_get_n_extensions (adapter);
+  resolvers = ide_buffer_get_symbol_resolvers (priv->buffer);
+  IDE_PTR_ARRAY_SET_FREE_FUNC (resolvers, g_object_unref);
 
-  if (!n_extensions)
+  if (resolvers->len == 0)
     {
       g_debug ("No symbol resolver is available");
-
       IDE_EXIT;
     }
 
   data = g_slice_new0 (FindReferencesTaskData);
-  data->resolvers = g_ptr_array_new_with_free_func (g_object_unref);
+  data->resolvers = g_steal_pointer (&resolvers);
   data->location = ide_buffer_get_insert_location (priv->buffer);
   ide_task_set_task_data (task, data, find_references_task_data_free);
 
-  ide_extension_set_adapter_foreach_by_priority (adapter, find_references_task_get_extension, data);
-  g_assert (data->resolvers->len > 0);
-
   resolver = g_ptr_array_index (data->resolvers, data->resolvers->len - 1);
 
   /* Try each symbol resolver one by one to find references. */
   ide_symbol_resolver_find_references_async (resolver,
                                              data->location,
+                                             ide_buffer_get_language_id (priv->buffer),
                                              NULL,
                                              ide_source_view_find_references_cb,
                                              g_steal_pointer (&task));
@@ -5377,6 +5266,21 @@ ide_source_view_real_reset (IdeSourceView *self)
   g_signal_emit (self, signals [SET_MODE], 0, NULL, IDE_SOURCE_VIEW_MODE_TYPE_PERMANENT);
 }
 
+static void
+ide_source_view_destroy (GtkWidget *widget)
+{
+  IdeSourceView *self = (IdeSourceView *)widget;
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
+  /* Ensure we release the buffer immediately */
+  if (priv->buffer_signals != NULL)
+    dzl_signal_group_set_target (priv->buffer_signals, NULL);
+
+  GTK_WIDGET_CLASS (ide_source_view_parent_class)->destroy (widget);
+}
+
 static void
 ide_source_view_dispose (GObject *object)
 {
@@ -5406,12 +5310,12 @@ ide_source_view_dispose (GObject *object)
   g_clear_object (&priv->hover);
   g_clear_object (&priv->completion);
   g_clear_object (&priv->capture);
-  g_clear_object (&priv->indenter_adapter);
+  ide_clear_and_destroy_object (&priv->indenter_adapter);
   g_clear_object (&priv->css_provider);
   g_clear_object (&priv->mode);
   g_clear_object (&priv->buffer_signals);
   g_clear_object (&priv->file_setting_bindings);
-  g_clear_object (&priv->omni_renderer);
+  g_clear_object (&priv->gutter);
 
   if (priv->command_str != NULL)
     {
@@ -5637,6 +5541,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
   widget_class->scroll_event = ide_source_view_scroll_event;
   widget_class->size_allocate = ide_source_view_size_allocate;
   widget_class->style_updated = ide_source_view_real_style_updated;
+  widget_class->destroy = ide_source_view_destroy;
 
   text_view_class->delete_from_cursor = ide_source_view_real_delete_from_cursor;
   text_view_class->draw_layer = ide_source_view_real_draw_layer;
@@ -6083,7 +5988,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
                   NULL, NULL, NULL,
                   G_TYPE_NONE,
                   1,
-                  IDE_TYPE_SOURCE_LOCATION);
+                  IDE_TYPE_LOCATION);
 
   signals [FORMAT_SELECTION] =
     g_signal_new_class_handler ("format-selection",
@@ -6569,6 +6474,9 @@ ide_source_view_init (IdeSourceView *self)
                                      0,
                                      NULL);
 
+  priv->show_line_numbers = TRUE;
+  priv->show_line_changes = TRUE;
+  priv->show_line_diagnostics = TRUE;
   priv->interactive_completion = TRUE;
   priv->target_line_column = 0;
   priv->snippets = g_queue_new ();
@@ -6620,8 +6528,8 @@ ide_source_view_init (IdeSourceView *self)
                                    self,
                                    G_CONNECT_SWAPPED);
   dzl_signal_group_connect_object (priv->buffer_signals,
-                                   "notify::file",
-                                   G_CALLBACK (ide_source_view__buffer_notify_file_cb),
+                                   "notify::file-settings",
+                                   G_CALLBACK (ide_source_view__buffer_notify_file_settings_cb),
                                    self,
                                    G_CONNECT_SWAPPED);
   dzl_signal_group_connect_object (priv->buffer_signals,
@@ -6770,7 +6678,7 @@ ide_source_view_get_show_line_changes (IdeSourceView *self)
 
   g_return_val_if_fail (IDE_IS_SOURCE_VIEW (self), FALSE);
 
-  return ide_omni_gutter_renderer_get_show_line_changes (priv->omni_renderer);
+  return priv->show_line_changes;
 }
 
 void
@@ -6781,8 +6689,13 @@ ide_source_view_set_show_line_changes (IdeSourceView *self,
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
 
-  ide_omni_gutter_renderer_set_show_line_changes (priv->omni_renderer, show_line_changes);
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_CHANGES]);
+  priv->show_line_changes = !!show_line_changes;
+
+  if (priv->gutter)
+    {
+      ide_gutter_set_show_line_changes (priv->gutter, show_line_changes);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_CHANGES]);
+    }
 }
 
 gboolean
@@ -6792,7 +6705,7 @@ ide_source_view_get_show_line_diagnostics (IdeSourceView *self)
 
   g_return_val_if_fail (IDE_IS_SOURCE_VIEW (self), FALSE);
 
-  return ide_omni_gutter_renderer_get_show_line_diagnostics (priv->omni_renderer);
+  return priv->show_line_diagnostics;
 }
 
 void
@@ -6803,8 +6716,13 @@ ide_source_view_set_show_line_diagnostics (IdeSourceView *self,
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
 
-  ide_omni_gutter_renderer_set_show_line_diagnostics (priv->omni_renderer, show_line_diagnostics);
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_DIAGNOSTICS]);
+  priv->show_line_diagnostics = !!show_line_diagnostics;
+
+  if (priv->gutter)
+    {
+      ide_gutter_set_show_line_diagnostics (priv->gutter, show_line_diagnostics);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_DIAGNOSTICS]);
+    }
 }
 
 gboolean
@@ -7787,7 +7705,7 @@ ide_source_view_get_show_line_numbers (IdeSourceView *self)
 
   g_return_val_if_fail (IDE_IS_SOURCE_VIEW (self), FALSE);
 
-  return ide_omni_gutter_renderer_get_show_line_numbers (priv->omni_renderer);
+  return priv->show_line_numbers;
 }
 
 void
@@ -7798,8 +7716,13 @@ ide_source_view_set_show_line_numbers (IdeSourceView *self,
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
 
-  ide_omni_gutter_renderer_set_show_line_numbers (priv->omni_renderer, show_line_numbers);
-  g_object_notify (G_OBJECT (self), "show-line-numbers");
+  priv->show_line_numbers = !!show_line_numbers;
+
+  if (priv->gutter)
+    {
+      ide_gutter_set_show_line_numbers (priv->gutter, show_line_numbers);
+      g_object_notify (G_OBJECT (self), "show-line-numbers");
+    }
 }
 
 gboolean
@@ -7851,3 +7774,56 @@ ide_source_view_has_snippet (IdeSourceView *self)
 
   return priv->snippets->length > 0;
 }
+
+/**
+ * ide_source_view_set_gutter:
+ * @self: a #IdeSourceView
+ * @gutter: an #IdeGutter
+ *
+ * Allows setting the gutter for the sourceview.
+ *
+ * Generally, this will always be #IdeOmniGutterRenderer. However, to avoid
+ * circular dependencies, an interface is used to allow plugins to set
+ * this object.
+ *
+ * Since: 3.32
+ */
+void
+ide_source_view_set_gutter (IdeSourceView *self,
+                            IdeGutter     *gutter)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+  GtkSourceGutter *left_gutter;
+
+  g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
+  g_return_if_fail (!gutter || IDE_IS_GUTTER (gutter));
+  g_return_if_fail (!gutter || GTK_SOURCE_IS_GUTTER_RENDERER (gutter));
+
+  if (gutter == priv->gutter)
+    return;
+
+  left_gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self),
+                                            GTK_TEXT_WINDOW_LEFT);
+
+  if (priv->gutter)
+    {
+      gtk_source_gutter_remove (left_gutter, GTK_SOURCE_GUTTER_RENDERER (priv->gutter));
+      g_clear_object (&priv->gutter);
+    }
+
+  if (gutter)
+    {
+      priv->gutter = g_object_ref_sink (gutter);
+      gtk_source_gutter_insert (left_gutter,
+                                GTK_SOURCE_GUTTER_RENDERER (gutter),
+                                0);
+      ide_gutter_set_show_line_numbers (priv->gutter, priv->show_line_numbers);
+      ide_gutter_set_show_line_changes (priv->gutter, priv->show_line_changes);
+      ide_gutter_set_show_line_diagnostics (priv->gutter, priv->show_line_diagnostics);
+      ide_gutter_style_changed (gutter);
+    }
+
+  g_object_notify (G_OBJECT (self), "show-line-changes");
+  g_object_notify (G_OBJECT (self), "show-line-diagnostics");
+  g_object_notify (G_OBJECT (self), "show-line-numbers");
+}
diff --git a/src/libide/sourceview/ide-source-view.h b/src/libide/sourceview/ide-source-view.h
index ddd25fc3a..763f2b162 100644
--- a/src/libide/sourceview/ide-source-view.h
+++ b/src/libide/sourceview/ide-source-view.h
@@ -20,16 +20,20 @@
 
 #pragma once
 
-#include <gtksourceview/gtksource.h>
+#if !defined (IDE_SOURCEVIEW_INSIDE) && !defined (IDE_SOURCEVIEW_COMPILATION)
+# error "Only <libide-sourceview.h> can be included directly."
+#endif
 
-#include "ide-types.h"
-#include "ide-version-macros.h"
+#include <gtksourceview/gtksource.h>
+#include <libide-code.h>
 
-#include "completion/ide-completion-types.h"
+#include "ide-completion-types.h"
+#include "ide-gutter.h"
+#include "ide-snippet-types.h"
 
 G_BEGIN_DECLS
 
-#define IDE_TYPE_SOURCE_VIEW  (ide_source_view_get_type())
+#define IDE_TYPE_SOURCE_VIEW (ide_source_view_get_type())
 
 IDE_AVAILABLE_IN_3_32
 G_DECLARE_DERIVABLE_TYPE (IdeSourceView, ide_source_view, IDE, SOURCE_VIEW, GtkSourceView)
@@ -48,6 +52,8 @@ typedef enum
  * @IDE_SOURCE_VIEW_MODE_MODAL: Modal
  *
  * The type of keyboard mode.
+ *
+ * Since: 3.32
  */
 typedef enum
 {
@@ -62,6 +68,8 @@ typedef enum
  * @IDE_SOURCE_VIEW_THEATRIC_SHRINK: shrink from selection location.
  *
  * The style of theatric.
+ *
+ * Since: 3.32
  */
 
 typedef enum
@@ -147,6 +155,8 @@ typedef enum
  *
  * Some of these movements may be modified by using the modify-repeat action.
  * First adjust the repeat and then perform the "movement" action.
+ *
+ * Since: 3.32
  */
 typedef enum
 {
@@ -268,7 +278,7 @@ struct _IdeSourceViewClass
   void (*delete_selection)            (IdeSourceView           *self);
   void (*end_macro)                   (IdeSourceView           *self);
   void (*focus_location)              (IdeSourceView           *self,
-                                       IdeSourceLocation       *location);
+                                       IdeLocation       *location);
   void (*goto_definition)             (IdeSourceView           *self);
   void (*hide_completion)             (IdeSourceView           *self);
   void (*indent_selection)            (IdeSourceView           *self,
@@ -339,29 +349,7 @@ struct _IdeSourceViewClass
   void (*copy_clipboard_extended)     (IdeSourceView           *self);
 
   /*< private >*/
-  gpointer _reserved1;
-  gpointer _reserved2;
-  gpointer _reserved3;
-  gpointer _reserved4;
-  gpointer _reserved5;
-  gpointer _reserved6;
-  gpointer _reserved7;
-  gpointer _reserved8;
-  gpointer _reserved9;
-  gpointer _reserved10;
-  gpointer _reserved11;
-  gpointer _reserved12;
-  gpointer _reserved13;
-  gpointer _reserved14;
-  gpointer _reserved15;
-  gpointer _reserved16;
-  gpointer _reserved17;
-  gpointer _reserved18;
-  gpointer _reserved19;
-  gpointer _reserved20;
-  gpointer _reserved21;
-  gpointer _reserved22;
-  gpointer _reserved23;
+  gpointer _reserved[32];
 };
 
 IDE_AVAILABLE_IN_3_32
@@ -511,12 +499,8 @@ IDE_AVAILABLE_IN_3_32
 IdeCompletion              *ide_source_view_get_completion            (IdeSourceView              *self);
 IDE_AVAILABLE_IN_3_32
 gboolean                    ide_source_view_is_processing_key         (IdeSourceView              *self);
-
-const gchar                *_ide_source_view_get_mode_name            (IdeSourceView              *self) 
G_GNUC_INTERNAL;
-void                        _ide_source_view_set_count                (IdeSourceView              *self,
-                                                                       gint                        count) 
G_GNUC_INTERNAL;
-void                        _ide_source_view_set_modifier             (IdeSourceView              *self,
-                                                                       gunichar                    modifier) 
G_GNUC_INTERNAL;
-GtkTextMark                *_ide_source_view_get_scroll_mark          (IdeSourceView              *self) 
G_GNUC_INTERNAL;
+IDE_AVAILABLE_IN_3_32
+void                        ide_source_view_set_gutter                (IdeSourceView              *self,
+                                                                       IdeGutter                  *gutter);
 
 G_END_DECLS
diff --git a/src/libide/sourceview/libide-sourceview.gresource.xml 
b/src/libide/sourceview/libide-sourceview.gresource.xml
new file mode 100644
index 000000000..52cfc8638
--- /dev/null
+++ b/src/libide/sourceview/libide-sourceview.gresource.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/libide-sourceview">
+    <file preprocess="xml-stripblanks">gtk/menus.ui</file>
+  </gresource>
+  <gresource prefix="/org/gnome/libide-sourceview/ui">
+    <file preprocess="xml-stripblanks">ide-completion-list-box-row.ui</file>
+    <file preprocess="xml-stripblanks">ide-completion-overlay.ui</file>
+    <file preprocess="xml-stripblanks">ide-completion-view.ui</file>
+    <file preprocess="xml-stripblanks">ide-completion-window.ui</file>
+  </gresource>
+</gresources>
diff --git a/src/libide/sourceview/libide-sourceview.h b/src/libide/sourceview/libide-sourceview.h
new file mode 100644
index 000000000..d8345b963
--- /dev/null
+++ b/src/libide/sourceview/libide-sourceview.h
@@ -0,0 +1,53 @@
+/* libide-sourceview.h
+ *
+ * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-code.h>
+
+G_BEGIN_DECLS
+
+#define IDE_SOURCEVIEW_INSIDE
+
+#include"ide-completion-context.h"
+#include"ide-completion-display.h"
+#include"ide-completion-proposal.h"
+#include"ide-completion-list-box-row.h"
+#include"ide-completion-provider.h"
+#include"ide-completion-types.h"
+#include"ide-completion.h"
+#include"ide-hover-context.h"
+#include"ide-hover-provider.h"
+#include"ide-line-change-gutter-renderer.h"
+#include"ide-gutter.h"
+#include"ide-indenter.h"
+#include"ide-snippet-chunk.h"
+#include"ide-snippet-context.h"
+#include"ide-snippet-parser.h"
+#include"ide-snippet-storage.h"
+#include"ide-snippet-types.h"
+#include"ide-snippet.h"
+#include"ide-source-search-context.h"
+#include"ide-source-view.h"
+#include"ide-text-util.h"
+
+#define IDE_SOURCEVIEW_INSIDE
+
+G_END_DECLS
diff --git a/src/libide/sourceview/meson.build b/src/libide/sourceview/meson.build
index 441203430..7d07a0b0c 100644
--- a/src/libide/sourceview/meson.build
+++ b/src/libide/sourceview/meson.build
@@ -1,46 +1,172 @@
-sourceview_headers = [
+libide_sourceview_header_dir = join_paths(libide_header_dir, 'sourceview')
+libide_sourceview_header_subdir = join_paths(libide_header_subdir, 'sourceview')
+libide_include_directories += include_directories('.')
+
+libide_sourceview_generated_sources = []
+libide_sourceview_generated_headers = []
+
+#
+# Public API Headers
+#
+
+libide_sourceview_private_headers = [
+  'ide-completion-list-box.h',
+  'ide-completion-overlay.h',
+  'ide-completion-private.h',
+  'ide-completion-view.h',
+  'ide-completion-window.h',
+  'ide-cursor.h',
+  'ide-hover-popover-private.h',
+  'ide-hover-private.h',
+  'ide-source-view-capture.h',
+  'ide-source-view-mode.h',
+  'ide-source-view-movements.h',
+  'ide-source-view-private.h',
+]
+
+libide_sourceview_public_headers = [
+  'ide-completion-context.h',
+  'ide-completion-display.h',
+  'ide-completion-list-box-row.h',
+  'ide-completion-proposal.h',
+  'ide-completion-provider.h',
+  'ide-completion-types.h',
+  'ide-completion.h',
+  'ide-gutter.h',
+  'ide-hover-context.h',
+  'ide-hover-provider.h',
   'ide-indenter.h',
-  'ide-language.h',
-  'ide-source-iter.h',
-  'ide-source-style-scheme.h',
-  'ide-source-view.h',
-  'ide-text-iter.h',
+  'ide-line-change-gutter-renderer.h',
+  'ide-snippet-chunk.h',
+  'ide-snippet-context.h',
+  'ide-snippet-parser.h',
+  'ide-snippet-storage.h',
+  'ide-snippet-types.h',
+  'ide-snippet.h',
   'ide-source-search-context.h',
+  'ide-source-view.h',
+  'ide-text-util.h',
+  'libide-sourceview.h',
 ]
 
-sourceview_sources = [
-  'ide-indenter.c',
-  'ide-language.c',
-  'ide-source-iter.c',
-  'ide-source-style-scheme.c',
-  'ide-source-view.c',
-  'ide-text-iter.c',
-  'ide-source-search-context.c',
+libide_sourceview_enum_headers = [
+  'ide-completion-types.h',
+  'ide-source-view.h',
 ]
 
-sourceview_private_sources = [
+install_headers(libide_sourceview_public_headers, subdir: libide_sourceview_header_subdir)
+
+#
+# Sources
+#
+
+libide_sourceview_private_sources = [
+  'ide-completion-list-box.c',
+  'ide-completion-overlay.c',
+  'ide-completion-view.c',
+  'ide-completion-window.c',
   'ide-cursor.c',
-  'ide-cursor.h',
-  'ide-omni-gutter-renderer.c',
-  'ide-omni-gutter-renderer.h',
+  'ide-hover.c',
+  'ide-hover-popover.c',
   'ide-line-change-gutter-renderer.c',
-  'ide-line-change-gutter-renderer.h',
   'ide-source-view-capture.c',
-  'ide-source-view-capture.h',
   'ide-source-view-mode.c',
-  'ide-source-view-mode.h',
   'ide-source-view-movements.c',
   'ide-source-view-shortcuts.c',
   'ide-text-util.c',
 ]
 
-sourceview_enums = [
-  'ide-source-view.h',
+libide_sourceview_public_sources = [
+  'ide-completion-proposal.c',
+  'ide-completion-provider.c',
+  'ide-completion-context.c',
+  'ide-completion-display.c',
+  'ide-completion-list-box-row.c',
+  'ide-completion.c',
+  'ide-gutter.c',
+  'ide-hover-context.c',
+  'ide-hover-provider.c',
+  'ide-indenter.c',
+  'ide-source-search-context.c',
+  'ide-source-view.c',
+  'ide-snippet.c',
+  'ide-snippet-chunk.c',
+  'ide-snippet-context.c',
+  'ide-snippet-parser.c',
+  'ide-snippet-storage.c',
+]
+
+#
+# Generated Resource Files
+#
+
+libide_sourceview_resources = gnome.compile_resources(
+  'ide-sourceview-resources',
+  'libide-sourceview.gresource.xml',
+  c_name: 'ide_sourceview',
+)
+libide_sourceview_generated_headers += [libide_sourceview_resources[1]]
+libide_sourceview_generated_sources += libide_sourceview_resources[0]
+
+#
+# Enum generation
+#
+
+libide_sourceview_enums = gnome.mkenums_simple('ide-source-view-enums',
+     body_prefix: '#include "config.h"',
+   header_prefix: '#include <libide-core.h>',
+       decorator: '_IDE_EXTERN',
+         sources: libide_sourceview_enum_headers,
+  install_header: true,
+     install_dir: libide_sourceview_header_dir,
+)
+libide_sourceview_generated_sources += [libide_sourceview_enums[0]]
+libide_sourceview_generated_headers += [libide_sourceview_enums[1]]
+
+
+#
+# Dependencies
+#
+
+libide_sourceview_deps = [
+  libgio_dep,
+  libgtk_dep,
+  libgtksource_dep,
+  libdazzle_dep,
+
+  libide_core_dep,
+  libide_threading_dep,
+  libide_code_dep,
+  libide_plugins_dep,
+  libide_io_dep,
+  libide_gui_dep,
 ]
 
-libide_public_headers += files(sourceview_headers)
-libide_public_sources += files(sourceview_sources)
-libide_private_sources += files(sourceview_private_sources)
-libide_enum_headers += files(sourceview_enums)
+#
+# Library Definitions
+#
+
+libide_sourceview = static_library('ide-sourceview-' + libide_api_version,
+                                   libide_sourceview_public_sources,
+                                   libide_sourceview_private_sources,
+                                   libide_sourceview_generated_sources,
+                                   libide_sourceview_generated_headers,
+   dependencies: libide_sourceview_deps,
+         c_args: libide_args + release_args + ['-DIDE_SOURCEVIEW_COMPILATION'],
+)
+
+libide_sourceview_dep = declare_dependency(
+              sources: libide_sourceview_private_headers + libide_sourceview_generated_headers,
+         dependencies: libide_sourceview_deps,
+           link_whole: libide_sourceview,
+  include_directories: include_directories('.'),
+)
 
-install_headers(sourceview_headers, subdir: join_paths(libide_header_subdir, 'sourceview'))
+gnome_builder_public_sources += files(libide_sourceview_public_sources)
+gnome_builder_public_headers += files(libide_sourceview_public_headers)
+gnome_builder_private_sources += files(libide_sourceview_private_sources)
+gnome_builder_private_headers += files(libide_sourceview_private_headers)
+gnome_builder_generated_headers += libide_sourceview_generated_headers
+gnome_builder_generated_sources += libide_sourceview_generated_sources
+gnome_builder_include_subdirs += libide_sourceview_header_subdir
+gnome_builder_gir_extra_args += ['--c-include=libide-sourceview.h', '-DIDE_SOURCEVIEW_COMPILATION']


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