Fix bad diff display near empty comment caused edits

In 974daeef2121 we fixed GERRIT-66, a bug about not showing comments
if they were outside of the context of an edit being displayed in the
viewer.  Unfortunately the fixed hinged around creating an empty Edit
object, thus forcing the hunk surrounding the comment to appear.  This
threw off the display code, causing it to render some lines twice, and
in other cases, to omit lines entirely.

We now filter out the unnecessary empty Edit instances within a hunk,
as they served their purpose to hold open the hunk's context large
enough for the viewer to get the lines necessary, but leaving them in
nearby to other Edits may cause display errors.

Bug: GERRIT-220
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java b/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
index 1f1b360..6e71f37 100644
--- a/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
+++ b/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
@@ -109,7 +109,7 @@
     } else {
       srcB = open(contentAct.getNewId());
     }
-    edits = contentAct.getEdits();
+    edits = new ArrayList<Edit>(contentAct.getEdits());
     ensureCommentsVisible(comments);
 
     dstA.setMissingNewlineAtEnd(srcA.isMissingNewlineAtEnd());
@@ -130,7 +130,8 @@
       for (int i = 0; i < srcA.size(); i++) {
         srcA.addLineTo(dstA, i);
       }
-      edits = Collections.singletonList(new Edit(srcA.size(), srcA.size()));
+      edits = new ArrayList<Edit>(1);
+      edits.add(new Edit(srcA.size(), srcA.size()));
     } else {
       if (BIG_FILE < Math.max(srcA.size(), srcB.size()) && 25 < context()) {
         settings.setContext(25);
@@ -143,7 +144,7 @@
       // whitespace settings requested. Instead we must rebuild our edit
       // list around the whitespace edit list.
       //
-      edits = contentWS.getEdits();
+      edits = new ArrayList<Edit>(contentWS.getEdits());
       ensureCommentsVisible(comments);
     }
 
@@ -185,15 +186,11 @@
       }
     }
 
-    // Build the final list as a copy, as we cannot modify the cached
-    // edit list we started out with. Also sort the final list by the
-    // index in A, so packContent can combine them correctly later.
+    // Sort the final list by the index in A, so packContent can combine
+    // them correctly later.
     //
-    final List<Edit> n = new ArrayList<Edit>(edits.size() + empty.size());
-    n.addAll(edits);
-    n.addAll(empty);
-    Collections.sort(n, EDIT_SORT);
-    edits = n;
+    edits.addAll(empty);
+    Collections.sort(edits, EDIT_SORT);
   }
 
   private void safeAdd(final List<Edit> empty, final Edit toAdd) {
@@ -313,8 +310,13 @@
           srcB.addLineTo(dstB, bCur++);
         }
 
-        if (end(curEdit, aCur, bCur) && ++curIdx < edits.size())
+        if (end(curEdit, aCur, bCur) && ++curIdx < edits.size()) {
           curEdit = edits.get(curIdx);
+          while (curEdit.getType() == Edit.Type.EMPTY && curEdit != endEdit) {
+            edits.remove(curIdx);
+            curEdit = edits.get(curIdx);
+          }
+        }
       }
     }
   }