@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "Revert "Make DifferentialChangesetParser explicitly map display to storage for comments""

This reverts commit 1c2222f26f60e6210dc63e38e845c7375abccace.

+137 -26
+13 -4
src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php
··· 154 154 $parser->setLeftSideCommentMapping($left_source, $left_new); 155 155 $parser->setWhitespaceMode($request->getStr('whitespace')); 156 156 157 + // Load both left-side and right-side inline comments. 158 + $inlines = $this->loadInlineComments( 159 + array($left_source, $right_source), 160 + $author_phid); 161 + 157 162 $phids = array(); 158 - $inlines = $this->loadInlineComments($id, $author_phid); 159 163 foreach ($inlines as $inline) { 160 164 $parser->parseInlineComment($inline); 161 165 $phids[$inline->getAuthorPHID()] = true; ··· 228 232 )); 229 233 } 230 234 231 - private function loadInlineComments($changeset_id, $author_phid) { 235 + private function loadInlineComments(array $changeset_ids, $author_phid) { 236 + $changeset_ids = array_unique(array_filter($changeset_ids)); 237 + if (!$changeset_ids) { 238 + return; 239 + } 240 + 232 241 return id(new DifferentialInlineComment())->loadAllWhere( 233 - 'changesetID = %d AND (commentID IS NOT NULL OR authorPHID = %s)', 234 - $changeset_id, 242 + 'changesetID IN (%Ld) AND (commentID IS NOT NULL OR authorPHID = %s)', 243 + $changeset_ids, 235 244 $author_phid); 236 245 } 237 246
+124 -22
src/applications/differential/parser/changeset/DifferentialChangesetParser.php
··· 39 39 protected $whitespaceMode = null; 40 40 41 41 protected $subparser; 42 - protected $oldChangesetID = null; 43 42 protected $noHighlight; 44 43 45 44 protected $renderCacheKey = null; ··· 47 46 private $handles; 48 47 private $user; 49 48 49 + private $leftSideChangesetID; 50 + private $leftSideAttachesToNewFile; 51 + 52 + private $rightSideChangesetID; 53 + private $rightSideAttachesToNewFile; 54 + 50 55 const CACHE_VERSION = 4; 51 56 52 57 const ATTR_GENERATED = 'attr:generated'; ··· 60 65 const WHITESPACE_IGNORE_TRAILING = 'ignore-trailing'; 61 66 const WHITESPACE_IGNORE_ALL = 'ignore-all'; 62 67 68 + /** 69 + * Configure which Changeset comments added to the right side of the visible 70 + * diff will be attached to. The ID must be the ID of a real Differential 71 + * Changeset. 72 + * 73 + * The complexity here is that we may show an arbitrary side of an arbitrary 74 + * changeset as either the left or right part of a diff. This method allows 75 + * the left and right halves of the displayed diff to be correctly mapped to 76 + * storage changesets. 77 + * 78 + * @param id The Differential Changeset ID that comments added to the right 79 + * side of the visible diff should be attached to. 80 + * @param bool If true, attach new comments to the right side of the storage 81 + * changeset. Note that this may be false, if the left side of 82 + * some storage changeset is being shown as the right side of 83 + * a display diff. 84 + * @return this 85 + */ 63 86 public function setRightSideCommentMapping($id, $is_new) { 64 - 87 + $this->rightSideChangesetID = $id; 88 + $this->rightSideAttachesToNewFile = $is_new; 89 + return $this; 65 90 } 66 91 92 + /** 93 + * See setRightSideCommentMapping(), but this sets information for the left 94 + * side of the display diff. 95 + */ 67 96 public function setLeftSideCommentMapping($id, $is_new) { 68 - 97 + $this->leftSideChangesetID = $id; 98 + $this->leftSideAttachesToNewFile = $is_new; 99 + return $this; 69 100 } 70 101 71 102 /** ··· 101 132 102 133 public function setWhitespaceMode($whitespace_mode) { 103 134 $this->whitespaceMode = $whitespace_mode; 104 - return $this; 105 - } 106 - 107 - public function setOldChangesetID($old_changeset_id) { 108 - $this->oldChangesetID = $old_changeset_id; 109 135 return $this; 110 136 } 111 137 ··· 236 262 } 237 263 238 264 public function parseInlineComment(DifferentialInlineComment $comment) { 239 - $this->comments[] = $comment; 265 + // Parse only comments which are actually visible. 266 + if ($this->isCommentVisibleOnRenderedDiff($comment)) { 267 + $this->comments[] = $comment; 268 + } 240 269 return $this; 241 270 } 242 271 ··· 837 866 $end = $comment->getLineNumber() + 838 867 $comment->getLineLength() + 839 868 self::LINES_CONTEXT; 840 - $new = $this->isCommentInNewFile($comment); 869 + $new = $this->isCommentOnRightSideWhenDisplayed($comment); 841 870 for ($ii = $start; $ii <= $end; $ii++) { 842 871 if ($new) { 843 872 $new_mask[$ii] = true; ··· 862 891 foreach ($this->comments as $comment) { 863 892 $final = $comment->getLineNumber() + 864 893 $comment->getLineLength(); 865 - if ($this->isCommentInNewFile($comment)) { 894 + if ($this->isCommentOnRightSideWhenDisplayed($comment)) { 866 895 $new_comments[$final][] = $comment; 867 896 } else { 868 897 $old_comments[$final][] = $comment; ··· 881 910 return $this->renderChangesetTable($this->changeset, $html); 882 911 } 883 912 884 - private function isCommentInNewFile(DifferentialInlineComment $comment) { 885 - if ($this->oldChangesetID) { 886 - return ($comment->getChangesetID() != $this->oldChangesetID); 887 - } else { 888 - return $comment->getIsNewFile(); 913 + /** 914 + * Determine if an inline comment will appear on the rendered diff, 915 + * taking into consideration which halves of which changesets will actually 916 + * be shown. 917 + * 918 + * @param DifferentialInlineComment Comment to test for visibility. 919 + * @return bool True if the comment is visible on the rendered diff. 920 + */ 921 + private function isCommentVisibleOnRenderedDiff( 922 + DifferentialInlineComment $comment) { 923 + 924 + $changeset_id = $comment->getChangesetID(); 925 + $is_new = $comment->getIsNewFile(); 926 + 927 + if ($changeset_id == $this->rightSideChangesetID && 928 + $is_new == $this->rightSideAttachesToNewFile) { 929 + return true; 889 930 } 931 + 932 + if ($changeset_id == $this->leftSideChangesetID && 933 + $is_new == $this->leftSideAttachesToNewFile) { 934 + return true; 935 + } 936 + 937 + return false; 938 + } 939 + 940 + 941 + /** 942 + * Determine if a comment will appear on the right side of the display diff. 943 + * Note that the comment must appear somewhere on the rendered changeset, as 944 + * per isCommentVisibleOnRenderedDiff(). 945 + * 946 + * @param DifferentialInlineComment Comment to test for display location. 947 + * @return bool True for right, false for left. 948 + */ 949 + private function isCommentOnRightSideWhenDisplayed( 950 + DifferentialInlineComment $comment) { 951 + 952 + if (!$this->isCommentVisibleOnRenderedDiff($comment)) { 953 + throw new Exception("Comment is not visible on changeset!"); 954 + } 955 + 956 + $changeset_id = $comment->getChangesetID(); 957 + $is_new = $comment->getIsNewFile(); 958 + 959 + if ($changeset_id == $this->rightSideChangesetID && 960 + $is_new == $this->rightSideAttachesToNewFile) { 961 + return true; 962 + } 963 + 964 + return false; 890 965 } 891 966 892 967 protected function renderShield($message, $more) { ··· 961 1036 962 1037 $range_len = min($range_len, $rows - $range_start); 963 1038 1039 + // Gaps - compute gaps in the visible display diff, where we will render 1040 + // "Show more context" spacers. This builds an aggregate $mask of all the 1041 + // lines we must show (because they are near changed lines, near inline 1042 + // comments, or the request has explicitly asked for them, i.e. resulting 1043 + // from the user clicking "show more") and then finds all the gaps between 1044 + // visible lines. If a gap is smaller than the context size, we just 1045 + // display it. Otherwise, we record it into $gaps and will render a 1046 + // "show more context" element instead of diff text below. 1047 + 964 1048 $gaps = array(); 965 1049 $gap_start = 0; 966 1050 $in_gap = false; ··· 989 1073 990 1074 $gaps = array_reverse($gaps); 991 1075 992 - $changeset = $this->changesetID; 993 1076 $reference = $this->getChangeset()->getRenderingReference(); 994 1077 1078 + $left_id = $this->leftSideChangesetID; 1079 + $right_id = $this->rightSideChangesetID; 1080 + 1081 + // "N" stands for 'new' and means the comment should attach to the new file 1082 + // when stored, i.e. DifferentialInlineComment->setIsNewFile(). 1083 + // "O" stands for 'old' and means the comment should attach to the old file. 1084 + 1085 + $left_char = $this->leftSideAttachesToNewFile 1086 + ? 'N' 1087 + : 'O'; 1088 + $right_char = $this->rightSideAttachesToNewFile 1089 + ? 'N' 1090 + : 'O'; 1091 + 995 1092 for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) { 996 1093 if (empty($mask[$ii])) { 1094 + // If we aren't going to show this line, we've just entered a gap. 1095 + // Pop information about the next gap off the $gaps stack and render 1096 + // an appropriate "Show more context" element. This branch eventually 1097 + // increments $ii by the entire size of the gap and then continues 1098 + // the loop. 997 1099 $gap = array_pop($gaps); 998 1100 $top = $gap[0]; 999 1101 $len = $gap[1]; ··· 1100 1202 $html[] = $context_not_available; 1101 1203 } 1102 1204 1103 - if ($o_num && $changeset) { 1104 - $o_id = ' id="C'.$changeset.'OL'.$o_num.'"'; 1205 + if ($o_num && $left_id) { 1206 + $o_id = ' id="C'.$left_id.$left_char.'L'.$o_num.'"'; 1105 1207 } else { 1106 1208 $o_id = null; 1107 1209 } 1108 1210 1109 - if ($n_num && $changeset) { 1110 - $n_id = ' id="C'.$changeset.'NL'.$n_num.'"'; 1211 + if ($n_num && $right_id) { 1212 + $n_id = ' id="C'.$right_id.$right_char.'L'.$n_num.'"'; 1111 1213 } else { 1112 1214 $n_id = null; 1113 1215 } ··· 1156 1258 ($comment->getAuthorPHID() == $user->getPHID()) && 1157 1259 (!$comment->getCommentID()); 1158 1260 1159 - $on_right = $this->isCommentInNewFile($comment); 1261 + $on_right = $this->isCommentOnRightSideWhenDisplayed($comment); 1160 1262 1161 1263 return id(new DifferentialInlineCommentView()) 1162 1264 ->setInlineComment($comment)