From 84f62bdf9a791e3925f080ea75212f5dbe893eb6 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 21 Apr 2015 06:59:09 -0700 Subject: [PATCH] Move ported inlines which appear on nonvisible lines backward so they show up Summary: Ref T7447. Ref T7870. See T7870 for a detailed description of this issue. NOTE: Replying to these inlines from the UI still does the wrong thing, because we use the database line number, not the UI line number. Test Plan: Before: {F377732} After: {F377733} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7447, T7870 Differential Revision: https://secure.phabricator.com/D12491 --- .../parser/DifferentialChangesetParser.php | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/src/applications/differential/parser/DifferentialChangesetParser.php b/src/applications/differential/parser/DifferentialChangesetParser.php index bf1b5e3d35..82c0a47519 100644 --- a/src/applications/differential/parser/DifferentialChangesetParser.php +++ b/src/applications/differential/parser/DifferentialChangesetParser.php @@ -933,12 +933,50 @@ final class DifferentialChangesetParser { $feedback_mask = array(); if ($this->comments) { + // If there are any comments which appear in sections of the file which + // we don't have, we're going to move them backwards to the closest + // earlier line. Two cases where this may happen are: + // + // - Porting ghost comments forward into a file which was mostly + // deleted. + // - Porting ghost comments forward from a full-context diff to a + // partial-context diff. + + list($old_backmap, $new_backmap) = $this->buildLineBackmaps(); + foreach ($this->comments as $comment) { + $new_side = $this->isCommentOnRightSideWhenDisplayed($comment); + + $line = $comment->getLineNumber(); + if ($new_side) { + $back_line = $new_backmap[$line]; + } else { + $back_line = $old_backmap[$line]; + } + + if ($back_line != $line) { + // TODO: This should probably be cleaner, but just be simple and + // obvious for now. + $ghost = $comment->getIsGhost(); + if ($ghost) { + $moved = pht( + 'This comment originally appeared on line %s, but that line '. + 'does not exist in this version of the diff. It has been '. + 'moved backward to the nearest line.', + new PhutilNumber($line)); + $ghost['reason'] = $ghost['reason']."\n\n".$moved; + $comment->setIsGhost($ghost); + } + + $comment->setLineNumber($back_line); + $comment->setLineLength(0); + + } + $start = max($comment->getLineNumber() - self::LINES_CONTEXT, 0); $end = $comment->getLineNumber() + $comment->getLineLength() + self::LINES_CONTEXT; - $new_side = $this->isCommentOnRightSideWhenDisplayed($comment); for ($ii = $start; $ii <= $end; $ii++) { if ($new_side) { $new_mask[$ii] = true; @@ -959,6 +997,7 @@ final class DifferentialChangesetParser { $feedback_mask[$ii] = true; } } + $this->comments = msort($this->comments, 'getID'); foreach ($this->comments as $comment) { $final = $comment->getLineNumber() + @@ -1483,4 +1522,48 @@ final class DifferentialChangesetParser { return $changesets; } + /** + * Build maps from lines comments appear on to actual lines. + */ + private function buildLineBackmaps() { + $old_back = array(); + $new_back = array(); + foreach ($this->old as $ii => $old) { + $old_back[$old['line']] = $old['line']; + } + foreach ($this->new as $ii => $new) { + $new_back[$new['line']] = $new['line']; + } + + $max_old_line = 0; + $max_new_line = 0; + foreach ($this->comments as $comment) { + if ($this->isCommentOnRightSideWhenDisplayed($comment)) { + $max_new_line = max($max_new_line, $comment->getLineNumber()); + } else { + $max_old_line = max($max_old_line, $comment->getLineNumber()); + } + } + + $cursor = 1; + for ($ii = 1; $ii <= $max_old_line; $ii++) { + if (empty($old_back[$ii])) { + $old_back[$ii] = $cursor; + } else { + $cursor = $old_back[$ii]; + } + } + + $cursor = 1; + for ($ii = 1; $ii <= $max_new_line; $ii++) { + if (empty($new_back[$ii])) { + $new_back[$ii] = $cursor; + } else { + $cursor = $new_back[$ii]; + } + } + + return array($old_back, $new_back); + } + } -- 2.54.0