Skip to content

Commit ccf28a8

Browse files
author
epriestley
committedJan 30, 2020
Fix an issue where the last line of block-based diffs could be incorrectly hidden
Summary: Fixes T13468. See that task for discussion. The older source-rendering code mixes "line number" / "1-based" lists with "block number" / "0-based" lists and then has other bugs which cancel this out. For block-based diffs, build an explicit block-based mask with only block numbers. This sort of sidesteps the whole issue. Test Plan: Viewed the diff with the original reproduction case, plus various other block-based diffs, including one-block image diffs, in unified and side-by-side mode. Didn't spot any oddities. Maniphest Tasks: T13468 Differential Revision: https://secure.phabricator.com/D20959
1 parent 12c3370 commit ccf28a8

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed
 

‎src/applications/differential/parser/DifferentialHunkParser.php

+64
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,77 @@ public function generateIntraLineDiffs() {
354354
return $this;
355355
}
356356

357+
public function generateVisibleBlocksMask($lines_context) {
358+
359+
// See T13468. This is similar to "generateVisibleLinesMask()", but
360+
// attempts to work around a series of bugs which cancel each other
361+
// out but make a mess of the intermediate steps.
362+
363+
$old = $this->getOldLines();
364+
$new = $this->getNewLines();
365+
366+
$length = max(count($old), count($new));
367+
368+
$visible_lines = array();
369+
for ($ii = 0; $ii < $length; $ii++) {
370+
$old_visible = (isset($old[$ii]) && $old[$ii]['type']);
371+
$new_visible = (isset($new[$ii]) && $new[$ii]['type']);
372+
373+
$visible_lines[$ii] = ($old_visible || $new_visible);
374+
}
375+
376+
$mask = array();
377+
$reveal_cursor = -1;
378+
for ($ii = 0; $ii < $length; $ii++) {
379+
380+
// If this line isn't visible, it isn't going to reveal anything.
381+
if (!$visible_lines[$ii]) {
382+
383+
// If it hasn't been revealed by a nearby line, mark it as masked.
384+
if (empty($mask[$ii])) {
385+
$mask[$ii] = false;
386+
}
387+
388+
continue;
389+
}
390+
391+
// If this line is visible, reveal all the lines nearby.
392+
393+
// First, compute the minimum and maximum offsets we want to reveal.
394+
$min_reveal = max($ii - $lines_context, 0);
395+
$max_reveal = min($ii + $lines_context, $length - 1);
396+
397+
// Naively, we'd do more work than necessary when revealing context for
398+
// several adjacent visible lines: we would mark all the overlapping
399+
// lines as revealed several times.
400+
401+
// To avoid duplicating work, keep track of the largest line we've
402+
// revealed to. Since we reveal context by marking every consecutive
403+
// line, we don't need to touch any line above it.
404+
$min_reveal = max($min_reveal, $reveal_cursor);
405+
406+
// Reveal the remaining unrevealed lines.
407+
for ($jj = $min_reveal; $jj <= $max_reveal; $jj++) {
408+
$mask[$jj] = true;
409+
}
410+
411+
// Move the cursor to the next line which may still need to be revealed.
412+
$reveal_cursor = $max_reveal + 1;
413+
}
414+
415+
$this->setVisibleLinesMask($mask);
416+
417+
return $mask;
418+
}
419+
357420
public function generateVisibleLinesMask($lines_context) {
358421
$old = $this->getOldLines();
359422
$new = $this->getNewLines();
360423
$max_length = max(count($old), count($new));
361424
$visible = false;
362425
$last = 0;
363426
$mask = array();
427+
364428
for ($cursor = -$lines_context; $cursor < $max_length; $cursor++) {
365429
$offset = $cursor + $lines_context;
366430
if ((isset($old[$offset]) && $old[$offset]['type']) ||

‎src/applications/files/diff/PhabricatorDocumentEngineBlocks.php

+2-9
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function newTwoUpLayout() {
5959
->parseHunksForLineData($changeset->getHunks())
6060
->reparseHunksForSpecialAttributes();
6161

62-
$hunk_parser->generateVisibleLinesMask(2);
62+
$hunk_parser->generateVisibleBlocksMask(2);
6363
$mask = $hunk_parser->getVisibleLinesMask();
6464

6565
$old_lines = $hunk_parser->getOldLines();
@@ -72,14 +72,7 @@ public function newTwoUpLayout() {
7272
$old_line = idx($old_lines, $ii);
7373
$new_line = idx($new_lines, $ii);
7474

75-
$is_visible = !empty($mask[$ii + 1]);
76-
77-
// TODO: There's currently a bug where one-line files get incorrectly
78-
// masked. This causes images to completely fail to render. Just ignore
79-
// the mask if it came back empty.
80-
if (!$mask) {
81-
$is_visible = true;
82-
}
75+
$is_visible = !empty($mask[$ii]);
8376

8477
if ($old_line) {
8578
$old_hash = rtrim($old_line['text'], "\n");

0 commit comments

Comments
 (0)
Failed to load comments.