From 0192c57f466c1d7c104cf40a8ecf16f83f5aa0f1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 Aug 2013 18:39:59 -0600 Subject: [PATCH] Fix corner case in RowMap::mapBufferRowRange w/ 0-buffer-row regions Fixes #688 The DisplayBuffer applies buffer and screen deltas to the row map as rows are inserted/removed from the buffer/screen. This can leave some of the regions in a weird state, such as mapping multiple screen rows to zero buffer rows. But next the DisplayBuffer applies any new mappings based on the replaced lines over the top of existing regions. These weirdly shaped regions should be overwritten by newly inserted regions, so at the end of the operation the row map makes sense again. This fixes a corner case where regions spanning 0 buffer rows at the very beginning of the row range were not being included in the set of regions to replace. This was in turn causing the RowMap to get into a bad state in certain situations involving soft-wrapped lines. --- spec/display-buffer-spec.coffee | 14 ++++++++++++++ spec/row-map-spec.coffee | 7 +++++++ src/row-map.coffee | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 6f9d7678c..95af52744 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -140,6 +140,20 @@ describe "DisplayBuffer", -> expect(changeHandler).toHaveBeenCalledWith(start: 3, end: 9, screenDelta: -6, bufferDelta: -4) + describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", -> + it "correctly renders the original wrapped line", -> + buffer = project.buildBuffer(null, '') + displayBuffer = new DisplayBuffer({buffer, tabLength, softWrapColumn: 30}) + + buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.") + buffer.insert([0, Infinity], '\n') + buffer.delete([[0, Infinity], [1, 0]]) + buffer.insert([0, Infinity], '\n') + + expect(displayBuffer.lineForRow(0).text).toBe "the quick brown fox jumps over " + expect(displayBuffer.lineForRow(1).text).toBe "the lazy dog." + expect(displayBuffer.lineForRow(2).text).toBe "" + describe "position translation", -> it "translates positions accounting for wrapped lines", -> # before any wrapped lines diff --git a/spec/row-map-spec.coffee b/spec/row-map-spec.coffee index aca260928..279ffc698 100644 --- a/spec/row-map-spec.coffee +++ b/spec/row-map-spec.coffee @@ -172,6 +172,13 @@ describe "RowMap", -> expect(map.bufferRowRangeForScreenRow(7)).toEqual [21, 22] expect(map.bufferRowRangeForScreenRow(8)).toEqual [22, 27] + it "replaces regions that cover 0 buffer rows at the start or end of the buffer row range", -> + map.mapBufferRowRange(0, 0, 1) + map.mapBufferRowRange(0, 1, 1) + map.mapBufferRowRange(1, 1, 1) + map.mapBufferRowRange(0, 1, 3) + expect(map.screenRowRangeForBufferRow(0)).toEqual [0, 3] + describe "when the row range straddles existing regions", -> it "splits the straddled regions and places the new region between them", -> # filler region 0 diff --git a/src/row-map.coffee b/src/row-map.coffee index 568c55ae7..0df603aad 100644 --- a/src/row-map.coffee +++ b/src/row-map.coffee @@ -159,7 +159,7 @@ class RowMap bufferRow = 0 screenRow = 0 for region, index in @regions - if (bufferRow + region.bufferRows) > targetBufferRow + if (bufferRow + region.bufferRows) > targetBufferRow or region.bufferRows == 0 and bufferRow == targetBufferRow return { region, index, screenRow, bufferRow } bufferRow += region.bufferRows screenRow += region.screenRows