Skip to content

Commit 0251cfe

Browse files
committed
fix: last line change may disable hunk operation in two-side diff
If the last line is deleted or added, it was impossible to stage, unstage or discard the last hunk in a two-side diff view, if the hunk was selected on the side where the last line is missing (that's the left side for added lines and the right side for deleted lines). Since the button(s) for hunk operations are on the right side of the diff view, it was easier to trigger this bug for a deleted last line. This bug was introduced in commit 6511d15 while rewriting the text diff views. This fixes the bug mentioned in #1950 (comment).
1 parent d373e18 commit 0251cfe

2 files changed

Lines changed: 28 additions & 39 deletions

File tree

src/ViewModels/TextDiffContext.cs

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -191,25 +191,32 @@ public TwoSideTextDiff(Models.DiffOption option, Models.TextDiff diff, TextDiffC
191191
_option = option;
192192
_data = diff;
193193

194-
foreach (var line in diff.Lines)
194+
var sourceIndices = new int[diff.Lines.Count];
195+
196+
for (var sourceIndex = 0; sourceIndex < diff.Lines.Count; sourceIndex++)
195197
{
198+
var line = diff.Lines[sourceIndex];
196199
switch (line.Type)
197200
{
198201
case Models.TextDiffLineType.Added:
202+
sourceIndices[New.Count] = sourceIndex;
199203
New.Add(line);
200204
break;
201205
case Models.TextDiffLineType.Deleted:
206+
sourceIndices[Old.Count] = sourceIndex;
202207
Old.Add(line);
203208
break;
204209
default:
205210
FillEmptyLines();
211+
sourceIndices[Old.Count] = sourceIndex;
206212
Old.Add(line);
207213
New.Add(line);
208214
break;
209215
}
210216
}
211217

212218
FillEmptyLines();
219+
_sourceIndices = ResizeSourceIndices(sourceIndices);
213220
TryKeepPrevState(previous, Old);
214221
}
215222

@@ -223,43 +230,9 @@ public override TextDiffContext SwitchMode()
223230
return new CombinedTextDiff(_option, _data, this);
224231
}
225232

226-
public void ConvertsToCombinedRange(ref int startLine, ref int endLine, bool isOldSide)
233+
public int ConvertToCombined(int line)
227234
{
228-
endLine = Math.Min(endLine, _data.Lines.Count - 1);
229-
230-
var oneSide = isOldSide ? Old : New;
231-
var firstContentLine = -1;
232-
for (int i = startLine; i <= endLine; i++)
233-
{
234-
var line = oneSide[i];
235-
if (line.Type != Models.TextDiffLineType.None)
236-
{
237-
firstContentLine = i;
238-
break;
239-
}
240-
}
241-
242-
if (firstContentLine < 0)
243-
return;
244-
245-
var endContentLine = -1;
246-
for (int i = Math.Min(endLine, oneSide.Count - 1); i >= startLine; i--)
247-
{
248-
var line = oneSide[i];
249-
if (line.Type != Models.TextDiffLineType.None)
250-
{
251-
endContentLine = i;
252-
break;
253-
}
254-
}
255-
256-
if (endContentLine < 0)
257-
return;
258-
259-
var firstContent = oneSide[firstContentLine];
260-
var endContent = oneSide[endContentLine];
261-
startLine = _data.Lines.IndexOf(firstContent);
262-
endLine = _data.Lines.IndexOf(endContent);
235+
return 0 <= line && line < _sourceIndices.Length ? _sourceIndices[line] : line;
263236
}
264237

265238
private void FillEmptyLines()
@@ -277,5 +250,19 @@ private void FillEmptyLines()
277250
New.Add(new Models.TextDiffLine());
278251
}
279252
}
253+
254+
private int[] ResizeSourceIndices(int[] sourceIndices)
255+
{
256+
var length = Old.Count; // same as `New.Count`
257+
258+
if (length == sourceIndices.Length)
259+
return sourceIndices;
260+
261+
var resized = new int[length];
262+
Array.Copy(sourceIndices, resized, length);
263+
return resized;
264+
}
265+
266+
private readonly int[] _sourceIndices;
280267
}
281268
}

src/Views/TextDiffView.axaml.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,8 @@ protected override void UpdateSelectedChunk(double y)
11831183
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
11841184
view.Bounds.Height;
11851185

1186-
diff.ConvertsToCombinedRange(ref startIdx, ref endIdx, IsOld);
1186+
startIdx = diff.ConvertToCombined(startIdx);
1187+
endIdx = diff.ConvertToCombined(endIdx);
11871188
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, false, IsOld));
11881189
}
11891190
else
@@ -1229,7 +1230,8 @@ protected override void UpdateSelectedChunk(double y)
12291230
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
12301231
view.Bounds.Height;
12311232

1232-
diff.ConvertsToCombinedRange(ref startIdx, ref endIdx, IsOld);
1233+
startIdx = diff.ConvertToCombined(startIdx);
1234+
endIdx = diff.ConvertToCombined(endIdx);
12331235
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, true, false));
12341236
}
12351237
}

0 commit comments

Comments
 (0)