From 829c50f5b07baaca82b6778283fad84f56fe3ce1 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 14 Sep 2016 15:04:11 -0400
Subject: [PATCH 18/44] FIXME: WIP on newlines in fixits

---
 gcc/edit-context.c | 84 ++++++++++++++++++++++++++++++++++++++++--------------
 gcc/edit-context.h |  5 ++--
 2 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/gcc/edit-context.c b/gcc/edit-context.c
index 26b43f2..3d60dfd 100644
--- a/gcc/edit-context.c
+++ b/gcc/edit-context.c
@@ -420,6 +420,9 @@ edited_file::print_diff (pretty_printer *pp, bool show_filenames)
 
   const int context_lines = 3;
 
+  /* Track new line numbers minus old line numbers.  */
+  int line_delta = 0;
+
   while (el)
     {
       int start_of_hunk = el->get_line_num ();
@@ -446,7 +449,9 @@ edited_file::print_diff (pretty_printer *pp, bool show_filenames)
       if (end_of_hunk > line_count)
 	end_of_hunk = line_count;
 
-      print_diff_hunk (pp, start_of_hunk, end_of_hunk);
+      int new_start_of_hunk = start_of_hunk + line_delta;
+      line_delta += print_diff_hunk (pp, start_of_hunk, end_of_hunk,
+				     new_start_of_hunk);
 
       el = m_edited_lines.successor (el->get_line_num ());
     }
@@ -454,24 +459,17 @@ edited_file::print_diff (pretty_printer *pp, bool show_filenames)
 
 /* Print one hunk within a unified diff to PP, covering the
    given range of lines.  OLD_START_OF_HUNK and OLD_END_OF_HUNK are
-   line numbers in the unedited version of the file.  */
+   line numbers in the unedited version of the file.
+   NEW_START_OF_HUNK is a line number in the edited version of the file.
+   Return the change in the line count within the hunk.  */
 
-void
+int
 edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
-			      int old_end_of_hunk)
+			      int old_end_of_hunk, int new_start_of_hunk)
 {
   int old_num_lines = old_end_of_hunk - old_start_of_hunk + 1;
-
-  // TODO: calculate new_num_lines based on if any newlines have been added
-#if 0
-  int new_num_lines = get_effective_line_count (start_of_hunk, end_of_hunk);
-  // FIXME: does this affect effective start-of-hunk numbering later on...
-#else
-  int new_num_lines = old_num_lines;
-#endif
-
-  int new_start_of_hunk = old_start_of_hunk;
-  //int new_end_of_hunk = old_end_of_hunk;
+  int new_num_lines
+    = get_effective_line_count (old_start_of_hunk, old_end_of_hunk);
 
   pp_string (pp, colorize_start (pp_show_color (pp), "diff-hunk"));
   pp_printf (pp, "@@ -%i,%i +%i,%i @@\n", old_start_of_hunk, old_num_lines,
@@ -504,6 +502,8 @@ edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
 	  line_num++;
 	}
     }
+
+  return new_num_lines - old_num_lines;
 }
 
 /* FIXME.  */
@@ -528,12 +528,16 @@ edited_file::print_run_of_changed_lines (pretty_printer *pp,
   /* Show new version of lines.  */
   pp_string (pp, colorize_start (pp_show_color (pp),
 				 "diff-insert"));
-  for (int line_num = start_of_run; line_num <= end_of_run; line_num++)
+  for (int old_line_num = start_of_run; old_line_num <= end_of_run;
+       old_line_num++)
     {
-      edited_line *el = get_line (line_num);
+      edited_line *el = get_line (old_line_num);
       gcc_assert (el);
-      print_diff_line (pp, '+', el->get_content (),
-		       el->get_len ());
+      auto_vec<effective_line> new_lines = el->get_effective_lines ();
+      int new_line_num;
+      effective_line *new_line;
+      FOR_EACH_VEC_ELT (new_lines, new_line_num, new_line)
+	print_diff_line (pp, '+', new_line->m_start, new_line->m_len);
     }
   pp_string (pp, colorize_stop (pp_show_color (pp)));
 }
@@ -552,6 +556,25 @@ edited_file::print_diff_line (pretty_printer *pp, char prefix_char,
   pp_character (pp, '\n');
 }
 
+/* FIXME.  */
+
+int
+edited_file::get_effective_line_count (int old_start_of_hunk,
+				       int old_end_of_hunk)
+{
+  int line_count = 0;
+  for (int old_line_num = old_start_of_hunk; old_line_num <= old_end_of_hunk;
+       old_line_num++)
+    {
+      edited_line *el = get_line (old_line_num);
+      if (el)
+	line_count += el->get_effective_lines ().length ();
+      else
+	line_count++;
+    }
+  return line_count;
+}
+
 /* Get the state of LINE within the file, or NULL if it is untouched.  */
 
 edited_line *
@@ -760,6 +783,27 @@ edited_line::apply_replace (int start_column,
   return true;
 }
 
+/* FIXME.  */
+
+auto_vec<effective_line>
+edited_line::get_effective_lines () const
+{
+  auto_vec<effective_line> result;
+  const char *line_start = m_content;
+  while (1)
+    {
+      const char *newline = strchr (line_start, '\n');
+      if (!newline)
+	break;
+      result.safe_push (effective_line (line_start,
+					newline - line_start));
+      line_start = newline + 1;
+    }
+  result.safe_push (effective_line (line_start,
+				    m_len - (line_start - m_content)));
+  return result;
+}
+
 /* Ensure that the buffer for m_content is at least large enough to hold
    a string of length LEN and its 0-terminator, doubling on repeated
    allocations.  */
@@ -1215,12 +1259,10 @@ test_applying_fixits_replace_containing_newline (const line_table_case &case_)
 
   /* Verify diff.  */
   auto_free <char *> diff = edit.generate_diff (false);
-#if 0
   ASSERT_STREQ ("@@ -1,1 +1,2 @@\n"
 		"-foo = bar ();\n"
 		"+foo\n"
 		"+  = bar ();\n", diff);
-#endif
 }
 
 /* Test applying a "remove" fixit.  */
diff --git a/gcc/edit-context.h b/gcc/edit-context.h
index ee9eed4..6a6ad20 100644
--- a/gcc/edit-context.h
+++ b/gcc/edit-context.h
@@ -112,12 +112,13 @@ class edited_file
  private:
   bool print_content (pretty_printer *pp);
   void print_diff (pretty_printer *pp, bool show_filenames);
-  void print_diff_hunk (pretty_printer *pp, int start_of_hunk,
-			int end_of_hunk);
+  int print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
+		       int old_end_of_hunk, int new_start_of_hunk);
   void print_run_of_changed_lines (pretty_printer *pp, int start_of_run,
 				   int end_of_run);
   void print_diff_line (pretty_printer *pp, char prefix_char,
 			const char *line, int line_size);
+  int get_effective_line_count (int old_start_of_hunk, int old_end_of_hunk);
   edited_line *get_or_insert_line (int line);
   int get_num_lines (bool *missing_trailing_newline);
 
-- 
1.8.5.3

