Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/differential/render/DifferentialChangesetRenderer.php b/src/applications/differential/render/DifferentialChangesetRenderer.php
index b7f78b5b68..26de5cb53b 100644
--- a/src/applications/differential/render/DifferentialChangesetRenderer.php
+++ b/src/applications/differential/render/DifferentialChangesetRenderer.php
@@ -1,708 +1,718 @@
<?php
abstract class DifferentialChangesetRenderer extends Phobject {
private $user;
private $changeset;
private $renderingReference;
private $renderPropertyChangeHeader;
private $isTopLevel;
private $isUndershield;
private $hunkStartLines;
private $oldLines;
private $newLines;
private $oldComments;
private $newComments;
private $oldChangesetID;
private $newChangesetID;
private $oldAttachesToNewFile;
private $newAttachesToNewFile;
private $highlightOld = array();
private $highlightNew = array();
private $codeCoverage;
private $handles;
private $markupEngine;
private $oldRender;
private $newRender;
private $originalOld;
private $originalNew;
private $gaps;
private $mask;
private $originalCharacterEncoding;
private $showEditAndReplyLinks;
private $canMarkDone;
private $objectOwnerPHID;
private $highlightingDisabled;
- private $scopeEngine;
+ private $scopeEngine = false;
private $depthOnlyLines;
private $oldFile = false;
private $newFile = false;
abstract public function getRendererKey();
public function setShowEditAndReplyLinks($bool) {
$this->showEditAndReplyLinks = $bool;
return $this;
}
public function getShowEditAndReplyLinks() {
return $this->showEditAndReplyLinks;
}
public function setHighlightingDisabled($highlighting_disabled) {
$this->highlightingDisabled = $highlighting_disabled;
return $this;
}
public function getHighlightingDisabled() {
return $this->highlightingDisabled;
}
public function setOriginalCharacterEncoding($original_character_encoding) {
$this->originalCharacterEncoding = $original_character_encoding;
return $this;
}
public function getOriginalCharacterEncoding() {
return $this->originalCharacterEncoding;
}
public function setIsUndershield($is_undershield) {
$this->isUndershield = $is_undershield;
return $this;
}
public function getIsUndershield() {
return $this->isUndershield;
}
public function setMask($mask) {
$this->mask = $mask;
return $this;
}
protected function getMask() {
return $this->mask;
}
public function setGaps($gaps) {
$this->gaps = $gaps;
return $this;
}
protected function getGaps() {
return $this->gaps;
}
public function setDepthOnlyLines(array $lines) {
$this->depthOnlyLines = $lines;
return $this;
}
public function getDepthOnlyLines() {
return $this->depthOnlyLines;
}
public function attachOldFile(PhabricatorFile $old = null) {
$this->oldFile = $old;
return $this;
}
public function getOldFile() {
if ($this->oldFile === false) {
throw new PhabricatorDataNotAttachedException($this);
}
return $this->oldFile;
}
public function hasOldFile() {
return (bool)$this->oldFile;
}
public function attachNewFile(PhabricatorFile $new = null) {
$this->newFile = $new;
return $this;
}
public function getNewFile() {
if ($this->newFile === false) {
throw new PhabricatorDataNotAttachedException($this);
}
return $this->newFile;
}
public function hasNewFile() {
return (bool)$this->newFile;
}
public function setOriginalNew($original_new) {
$this->originalNew = $original_new;
return $this;
}
protected function getOriginalNew() {
return $this->originalNew;
}
public function setOriginalOld($original_old) {
$this->originalOld = $original_old;
return $this;
}
protected function getOriginalOld() {
return $this->originalOld;
}
public function setNewRender($new_render) {
$this->newRender = $new_render;
return $this;
}
protected function getNewRender() {
return $this->newRender;
}
public function setOldRender($old_render) {
$this->oldRender = $old_render;
return $this;
}
protected function getOldRender() {
return $this->oldRender;
}
public function setMarkupEngine(PhabricatorMarkupEngine $markup_engine) {
$this->markupEngine = $markup_engine;
return $this;
}
public function getMarkupEngine() {
return $this->markupEngine;
}
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
protected function getHandles() {
return $this->handles;
}
public function setCodeCoverage($code_coverage) {
$this->codeCoverage = $code_coverage;
return $this;
}
protected function getCodeCoverage() {
return $this->codeCoverage;
}
public function setHighlightNew($highlight_new) {
$this->highlightNew = $highlight_new;
return $this;
}
protected function getHighlightNew() {
return $this->highlightNew;
}
public function setHighlightOld($highlight_old) {
$this->highlightOld = $highlight_old;
return $this;
}
protected function getHighlightOld() {
return $this->highlightOld;
}
public function setNewAttachesToNewFile($attaches) {
$this->newAttachesToNewFile = $attaches;
return $this;
}
protected function getNewAttachesToNewFile() {
return $this->newAttachesToNewFile;
}
public function setOldAttachesToNewFile($attaches) {
$this->oldAttachesToNewFile = $attaches;
return $this;
}
protected function getOldAttachesToNewFile() {
return $this->oldAttachesToNewFile;
}
public function setNewChangesetID($new_changeset_id) {
$this->newChangesetID = $new_changeset_id;
return $this;
}
protected function getNewChangesetID() {
return $this->newChangesetID;
}
public function setOldChangesetID($old_changeset_id) {
$this->oldChangesetID = $old_changeset_id;
return $this;
}
protected function getOldChangesetID() {
return $this->oldChangesetID;
}
public function setNewComments(array $new_comments) {
foreach ($new_comments as $line_number => $comments) {
assert_instances_of($comments, 'PhabricatorInlineCommentInterface');
}
$this->newComments = $new_comments;
return $this;
}
protected function getNewComments() {
return $this->newComments;
}
public function setOldComments(array $old_comments) {
foreach ($old_comments as $line_number => $comments) {
assert_instances_of($comments, 'PhabricatorInlineCommentInterface');
}
$this->oldComments = $old_comments;
return $this;
}
protected function getOldComments() {
return $this->oldComments;
}
public function setNewLines(array $new_lines) {
$this->newLines = $new_lines;
return $this;
}
protected function getNewLines() {
return $this->newLines;
}
public function setOldLines(array $old_lines) {
$this->oldLines = $old_lines;
return $this;
}
protected function getOldLines() {
return $this->oldLines;
}
public function setHunkStartLines(array $hunk_start_lines) {
$this->hunkStartLines = $hunk_start_lines;
return $this;
}
protected function getHunkStartLines() {
return $this->hunkStartLines;
}
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
protected function getUser() {
return $this->user;
}
public function setChangeset(DifferentialChangeset $changeset) {
$this->changeset = $changeset;
return $this;
}
protected function getChangeset() {
return $this->changeset;
}
public function setRenderingReference($rendering_reference) {
$this->renderingReference = $rendering_reference;
return $this;
}
protected function getRenderingReference() {
return $this->renderingReference;
}
public function setRenderPropertyChangeHeader($should_render) {
$this->renderPropertyChangeHeader = $should_render;
return $this;
}
private function shouldRenderPropertyChangeHeader() {
return $this->renderPropertyChangeHeader;
}
public function setIsTopLevel($is) {
$this->isTopLevel = $is;
return $this;
}
private function getIsTopLevel() {
return $this->isTopLevel;
}
public function setCanMarkDone($can_mark_done) {
$this->canMarkDone = $can_mark_done;
return $this;
}
public function getCanMarkDone() {
return $this->canMarkDone;
}
public function setObjectOwnerPHID($phid) {
$this->objectOwnerPHID = $phid;
return $this;
}
public function getObjectOwnerPHID() {
return $this->objectOwnerPHID;
}
final public function renderChangesetTable($content) {
$props = null;
if ($this->shouldRenderPropertyChangeHeader()) {
$props = $this->renderPropertyChangeHeader();
}
$notice = null;
if ($this->getIsTopLevel()) {
$force = (!$content && !$props);
$notice = $this->renderChangeTypeHeader($force);
}
$undershield = null;
if ($this->getIsUndershield()) {
$undershield = $this->renderUndershieldHeader();
}
$result = array(
$notice,
$props,
$undershield,
$content,
);
return hsprintf('%s', $result);
}
abstract public function isOneUpRenderer();
abstract public function renderTextChange(
$range_start,
$range_len,
$rows);
abstract public function renderFileChange(
$old = null,
$new = null,
$id = 0,
$vs = 0);
abstract protected function renderChangeTypeHeader($force);
abstract protected function renderUndershieldHeader();
protected function didRenderChangesetTableContents($contents) {
return $contents;
}
/**
* Render a "shield" over the diff, with a message like "This file is
* generated and does not need to be reviewed." or "This file was completely
* deleted." This UI element hides unimportant text so the reviewer doesn't
* need to scroll past it.
*
* The shield includes a link to view the underlying content. This link
* may force certain rendering modes when the link is clicked:
*
* - `"default"`: Render the diff normally, as though it was not
* shielded. This is the default and appropriate if the underlying
* diff is a normal change, but was hidden for reasons of not being
* important (e.g., generated code).
* - `"text"`: Force the text to be shown. This is probably only relevant
* when a file is not changed.
* - `"none"`: Don't show the link (e.g., text not available).
*
* @param string Message explaining why the diff is hidden.
* @param string|null Force mode, see above.
* @return string Shield markup.
*/
abstract public function renderShield($message, $force = 'default');
abstract protected function renderPropertyChangeHeader();
protected function buildPrimitives($range_start, $range_len) {
$primitives = array();
$hunk_starts = $this->getHunkStartLines();
$mask = $this->getMask();
$gaps = $this->getGaps();
$old = $this->getOldLines();
$new = $this->getNewLines();
$old_render = $this->getOldRender();
$new_render = $this->getNewRender();
$old_comments = $this->getOldComments();
$new_comments = $this->getNewComments();
$size = count($old);
for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) {
if (empty($mask[$ii])) {
list($top, $len) = array_pop($gaps);
$primitives[] = array(
'type' => 'context',
'top' => $top,
'len' => $len,
);
$ii += ($len - 1);
continue;
}
$ospec = array(
'type' => 'old',
'htype' => null,
'cursor' => $ii,
'line' => null,
'oline' => null,
'render' => null,
);
$nspec = array(
'type' => 'new',
'htype' => null,
'cursor' => $ii,
'line' => null,
'oline' => null,
'render' => null,
'copy' => null,
'coverage' => null,
);
if (isset($old[$ii])) {
$ospec['line'] = (int)$old[$ii]['line'];
$nspec['oline'] = (int)$old[$ii]['line'];
$ospec['htype'] = $old[$ii]['type'];
if (isset($old_render[$ii])) {
$ospec['render'] = $old_render[$ii];
}
}
if (isset($new[$ii])) {
$nspec['line'] = (int)$new[$ii]['line'];
$ospec['oline'] = (int)$new[$ii]['line'];
$nspec['htype'] = $new[$ii]['type'];
if (isset($new_render[$ii])) {
$nspec['render'] = $new_render[$ii];
}
}
if (isset($hunk_starts[$ospec['line']])) {
$primitives[] = array(
'type' => 'no-context',
);
}
$primitives[] = $ospec;
$primitives[] = $nspec;
if ($ospec['line'] !== null && isset($old_comments[$ospec['line']])) {
foreach ($old_comments[$ospec['line']] as $comment) {
$primitives[] = array(
'type' => 'inline',
'comment' => $comment,
'right' => false,
);
}
}
if ($nspec['line'] !== null && isset($new_comments[$nspec['line']])) {
foreach ($new_comments[$nspec['line']] as $comment) {
$primitives[] = array(
'type' => 'inline',
'comment' => $comment,
'right' => true,
);
}
}
if ($hunk_starts && ($ii == $size - 1)) {
$primitives[] = array(
'type' => 'no-context',
);
}
}
if ($this->isOneUpRenderer()) {
$primitives = $this->processPrimitivesForOneUp($primitives);
}
return $primitives;
}
private function processPrimitivesForOneUp(array $primitives) {
// Primitives come out of buildPrimitives() in two-up format, because it
// is the most general, flexible format. To put them into one-up format,
// we need to filter and reorder them. In particular:
//
// - We discard unchanged lines in the old file; in one-up format, we
// render them only once.
// - We group contiguous blocks of old-modified and new-modified lines, so
// they render in "block of old, block of new" order instead of
// alternating old and new lines.
$out = array();
$old_buf = array();
$new_buf = array();
foreach ($primitives as $primitive) {
$type = $primitive['type'];
if ($type == 'old') {
if (!$primitive['htype']) {
// This is a line which appears in both the old file and the new
// file, or the spacer corresponding to a line added in the new file.
// Ignore it when rendering a one-up diff.
continue;
}
$old_buf[] = $primitive;
} else if ($type == 'new') {
if ($primitive['line'] === null) {
// This is an empty spacer corresponding to a line removed from the
// old file. Ignore it when rendering a one-up diff.
continue;
}
if (!$primitive['htype']) {
// If this line is the same in both versions of the file, put it in
// the old line buffer. This makes sure inlines on old, unchanged
// lines end up in the right place.
// First, we need to flush the line buffers if they're not empty.
if ($old_buf) {
$out[] = $old_buf;
$old_buf = array();
}
if ($new_buf) {
$out[] = $new_buf;
$new_buf = array();
}
$old_buf[] = $primitive;
} else {
$new_buf[] = $primitive;
}
} else if ($type == 'context' || $type == 'no-context') {
$out[] = $old_buf;
$out[] = $new_buf;
$old_buf = array();
$new_buf = array();
$out[] = array($primitive);
} else if ($type == 'inline') {
// If this inline is on the left side, put it after the old lines.
if (!$primitive['right']) {
$out[] = $old_buf;
$out[] = array($primitive);
$old_buf = array();
} else {
$out[] = $old_buf;
$out[] = $new_buf;
$out[] = array($primitive);
$old_buf = array();
$new_buf = array();
}
} else {
throw new Exception(pht("Unknown primitive type '%s'!", $primitive));
}
}
$out[] = $old_buf;
$out[] = $new_buf;
$out = array_mergev($out);
return $out;
}
protected function getChangesetProperties($changeset) {
$old = $changeset->getOldProperties();
$new = $changeset->getNewProperties();
// When adding files, don't show the uninteresting 644 filemode change.
if ($changeset->getChangeType() == DifferentialChangeType::TYPE_ADD &&
$new == array('unix:filemode' => '100644')) {
unset($new['unix:filemode']);
}
// Likewise when removing files.
if ($changeset->getChangeType() == DifferentialChangeType::TYPE_DELETE &&
$old == array('unix:filemode' => '100644')) {
unset($old['unix:filemode']);
}
$metadata = $changeset->getMetadata();
if ($this->hasOldFile()) {
$file = $this->getOldFile();
if ($file->getImageWidth()) {
$dimensions = $file->getImageWidth().'x'.$file->getImageHeight();
$old['file:dimensions'] = $dimensions;
}
$old['file:mimetype'] = $file->getMimeType();
$old['file:size'] = phutil_format_bytes($file->getByteSize());
} else {
$old['file:mimetype'] = idx($metadata, 'old:file:mime-type');
$size = idx($metadata, 'old:file:size');
if ($size !== null) {
$old['file:size'] = phutil_format_bytes($size);
}
}
if ($this->hasNewFile()) {
$file = $this->getNewFile();
if ($file->getImageWidth()) {
$dimensions = $file->getImageWidth().'x'.$file->getImageHeight();
$new['file:dimensions'] = $dimensions;
}
$new['file:mimetype'] = $file->getMimeType();
$new['file:size'] = phutil_format_bytes($file->getByteSize());
} else {
$new['file:mimetype'] = idx($metadata, 'new:file:mime-type');
$size = idx($metadata, 'new:file:size');
if ($size !== null) {
$new['file:size'] = phutil_format_bytes($size);
}
}
return array($old, $new);
}
public function renderUndoTemplates() {
$views = array(
'l' => id(new PHUIDiffInlineCommentUndoView())->setIsOnRight(false),
'r' => id(new PHUIDiffInlineCommentUndoView())->setIsOnRight(true),
);
foreach ($views as $key => $view) {
$scaffold = $this->getRowScaffoldForInline($view);
$views[$key] = id(new PHUIDiffInlineCommentTableScaffold())
->addRowScaffold($scaffold);
}
return $views;
}
-
final protected function getScopeEngine() {
- if (!$this->scopeEngine) {
- $line_map = $this->getNewLineTextMap();
+ if ($this->scopeEngine === false) {
+ $hunk_starts = $this->getHunkStartLines();
+
+ // If this change is missing context, don't try to identify scopes, since
+ // we won't really be able to get anywhere.
+ $has_multiple_hunks = (count($hunk_starts) > 1);
+ $has_offset_hunks = (head_key($hunk_starts) != 1);
+ $missing_context = ($has_multiple_hunks || $has_offset_hunks);
- $scope_engine = id(new PhabricatorDiffScopeEngine())
- ->setLineTextMap($line_map);
+ if ($missing_context) {
+ $scope_engine = null;
+ } else {
+ $line_map = $this->getNewLineTextMap();
+ $scope_engine = id(new PhabricatorDiffScopeEngine())
+ ->setLineTextMap($line_map);
+ }
$this->scopeEngine = $scope_engine;
}
return $this->scopeEngine;
}
private function getNewLineTextMap() {
$new = $this->getNewLines();
$text_map = array();
foreach ($new as $new_line) {
if (!isset($new_line['line'])) {
continue;
}
$text_map[$new_line['line']] = $new_line['text'];
}
return $text_map;
}
}
diff --git a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
index c37655bb93..7efd29519e 100644
--- a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
+++ b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
@@ -1,460 +1,460 @@
<?php
final class DifferentialChangesetTwoUpRenderer
extends DifferentialChangesetHTMLRenderer {
private $newOffsetMap;
public function isOneUpRenderer() {
return false;
}
protected function getRendererTableClass() {
return 'diff-2up';
}
public function getRendererKey() {
return '2up';
}
protected function renderColgroup() {
return phutil_tag('colgroup', array(), array(
phutil_tag('col', array('class' => 'num')),
phutil_tag('col', array('class' => 'left')),
phutil_tag('col', array('class' => 'num')),
phutil_tag('col', array('class' => 'copy')),
phutil_tag('col', array('class' => 'right')),
phutil_tag('col', array('class' => 'cov')),
));
}
public function renderTextChange(
$range_start,
$range_len,
$rows) {
$hunk_starts = $this->getHunkStartLines();
$context_not_available = null;
if ($hunk_starts) {
$context_not_available = javelin_tag(
'tr',
array(
'sigil' => 'context-target',
),
phutil_tag(
'td',
array(
'colspan' => 6,
'class' => 'show-more',
),
pht('Context not available.')));
}
$html = array();
$old_lines = $this->getOldLines();
$new_lines = $this->getNewLines();
$gaps = $this->getGaps();
$reference = $this->getRenderingReference();
list($left_prefix, $right_prefix) = $this->getLineIDPrefixes();
$changeset = $this->getChangeset();
$copy_lines = idx($changeset->getMetadata(), 'copy:lines', array());
$highlight_old = $this->getHighlightOld();
$highlight_new = $this->getHighlightNew();
$old_render = $this->getOldRender();
$new_render = $this->getNewRender();
$original_left = $this->getOriginalOld();
$original_right = $this->getOriginalNew();
$mask = $this->getMask();
$scope_engine = $this->getScopeEngine();
$offset_map = null;
$depth_only = $this->getDepthOnlyLines();
for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) {
if (empty($mask[$ii])) {
// If we aren't going to show this line, we've just entered a gap.
// Pop information about the next gap off the $gaps stack and render
// an appropriate "Show more context" element. This branch eventually
// increments $ii by the entire size of the gap and then continues
// the loop.
$gap = array_pop($gaps);
$top = $gap[0];
$len = $gap[1];
$contents = $this->renderShowContextLinks($top, $len, $rows);
$is_last_block = false;
if ($ii + $len >= $rows) {
$is_last_block = true;
}
$context_text = null;
$context_line = null;
- if (!$is_last_block) {
+ if (!$is_last_block && $scope_engine) {
$target_line = $new_lines[$ii + $len]['line'];
$context_line = $scope_engine->getScopeStart($target_line);
if ($context_line !== null) {
// The scope engine returns a line number in the file. We need
// to map that back to a display offset in the diff.
if (!$offset_map) {
$offset_map = $this->getNewLineToOffsetMap();
}
$offset = $offset_map[$context_line];
$context_text = $new_render[$offset];
}
}
$container = javelin_tag(
'tr',
array(
'sigil' => 'context-target',
),
array(
phutil_tag(
'td',
array(
'class' => 'show-context-line n left-context',
)),
phutil_tag(
'td',
array(
'class' => 'show-more',
),
$contents),
phutil_tag(
'td',
array(
'class' => 'show-context-line n',
'data-n' => $context_line,
)),
phutil_tag(
'td',
array(
'colspan' => 3,
'class' => 'show-context',
),
// TODO: [HTML] Escaping model here isn't ideal.
phutil_safe_html($context_text)),
));
$html[] = $container;
$ii += ($len - 1);
continue;
}
$o_num = null;
$o_classes = '';
$o_text = null;
if (isset($old_lines[$ii])) {
$o_num = $old_lines[$ii]['line'];
$o_text = isset($old_render[$ii]) ? $old_render[$ii] : null;
if ($old_lines[$ii]['type']) {
if ($old_lines[$ii]['type'] == '\\') {
$o_text = $old_lines[$ii]['text'];
$o_class = 'comment';
} else if ($original_left && !isset($highlight_old[$o_num])) {
$o_class = 'old-rebase';
} else if (empty($new_lines[$ii])) {
$o_class = 'old old-full';
} else {
$o_class = 'old';
}
$o_classes = $o_class;
}
}
$n_copy = hsprintf('<td class="copy" />');
$n_cov = null;
$n_colspan = 2;
$n_classes = '';
$n_num = null;
$n_text = null;
if (isset($new_lines[$ii])) {
$n_num = $new_lines[$ii]['line'];
$n_text = isset($new_render[$ii]) ? $new_render[$ii] : null;
$coverage = $this->getCodeCoverage();
if ($coverage !== null) {
if (empty($coverage[$n_num - 1])) {
$cov_class = 'N';
} else {
$cov_class = $coverage[$n_num - 1];
}
$cov_class = 'cov-'.$cov_class;
$n_cov = phutil_tag('td', array('class' => "cov {$cov_class}"));
$n_colspan--;
}
if ($new_lines[$ii]['type']) {
if ($new_lines[$ii]['type'] == '\\') {
$n_text = $new_lines[$ii]['text'];
$n_class = 'comment';
} else if ($original_right && !isset($highlight_new[$n_num])) {
$n_class = 'new-rebase';
} else if (empty($old_lines[$ii])) {
$n_class = 'new new-full';
} else {
// NOTE: At least for the moment, I'm intentionally clearing the
// line highlighting only on the right side of the diff when a
// line has only depth changes. When a block depth is decreased,
// this gives us a large color block on the left (to make it easy
// to see the depth change) but a clean diff on the right (to make
// it easy to pick out actual code changes).
if (isset($depth_only[$ii])) {
$n_class = '';
} else {
$n_class = 'new';
}
}
$n_classes = $n_class;
$not_copied =
// If this line only changed depth, copy markers are pointless.
(!isset($copy_lines[$n_num])) ||
(isset($depth_only[$ii])) ||
($new_lines[$ii]['type'] == '\\');
if ($not_copied) {
$n_copy = phutil_tag('td', array('class' => 'copy'));
} else {
list($orig_file, $orig_line, $orig_type) = $copy_lines[$n_num];
$title = ($orig_type == '-' ? 'Moved' : 'Copied').' from ';
if ($orig_file == '') {
$title .= "line {$orig_line}";
} else {
$title .=
basename($orig_file).
":{$orig_line} in dir ".
dirname('/'.$orig_file);
}
$class = ($orig_type == '-' ? 'new-move' : 'new-copy');
$n_copy = javelin_tag(
'td',
array(
'meta' => array(
'msg' => $title,
),
'class' => 'copy '.$class,
));
}
}
}
if (isset($hunk_starts[$o_num])) {
$html[] = $context_not_available;
}
if ($o_num && $left_prefix) {
$o_id = $left_prefix.$o_num;
} else {
$o_id = null;
}
if ($n_num && $right_prefix) {
$n_id = $right_prefix.$n_num;
} else {
$n_id = null;
}
$old_comments = $this->getOldComments();
$new_comments = $this->getNewComments();
$scaffolds = array();
if ($o_num && isset($old_comments[$o_num])) {
foreach ($old_comments[$o_num] as $comment) {
$inline = $this->buildInlineComment(
$comment,
$on_right = false);
$scaffold = $this->getRowScaffoldForInline($inline);
if ($n_num && isset($new_comments[$n_num])) {
foreach ($new_comments[$n_num] as $key => $new_comment) {
if ($comment->isCompatible($new_comment)) {
$companion = $this->buildInlineComment(
$new_comment,
$on_right = true);
$scaffold->addInlineView($companion);
unset($new_comments[$n_num][$key]);
break;
}
}
}
$scaffolds[] = $scaffold;
}
}
if ($n_num && isset($new_comments[$n_num])) {
foreach ($new_comments[$n_num] as $comment) {
$inline = $this->buildInlineComment(
$comment,
$on_right = true);
$scaffolds[] = $this->getRowScaffoldForInline($inline);
}
}
$old_number = phutil_tag(
'td',
array(
'id' => $o_id,
'class' => $o_classes.' n',
'data-n' => $o_num,
));
$new_number = phutil_tag(
'td',
array(
'id' => $n_id,
'class' => $n_classes.' n',
'data-n' => $n_num,
));
$html[] = phutil_tag('tr', array(), array(
$old_number,
phutil_tag(
'td',
array(
'class' => $o_classes,
'data-copy-mode' => 'copy-l',
),
$o_text),
$new_number,
$n_copy,
phutil_tag(
'td',
array(
'class' => $n_classes,
'colspan' => $n_colspan,
'data-copy-mode' => 'copy-r',
),
$n_text),
$n_cov,
));
if ($context_not_available && ($ii == $rows - 1)) {
$html[] = $context_not_available;
}
foreach ($scaffolds as $scaffold) {
$html[] = $scaffold;
}
}
return $this->wrapChangeInTable(phutil_implode_html('', $html));
}
public function renderFileChange(
$old_file = null,
$new_file = null,
$id = 0,
$vs = 0) {
$old = null;
if ($old_file) {
$old = $this->renderImageStage($old_file);
}
$new = null;
if ($new_file) {
$new = $this->renderImageStage($new_file);
}
// If we don't have an explicit "vs" changeset, it's the left side of the
// "id" changeset.
if (!$vs) {
$vs = $id;
}
$html_old = array();
$html_new = array();
foreach ($this->getOldComments() as $on_line => $comment_group) {
foreach ($comment_group as $comment) {
$inline = $this->buildInlineComment(
$comment,
$on_right = false);
$html_old[] = $this->getRowScaffoldForInline($inline);
}
}
foreach ($this->getNewComments() as $lin_line => $comment_group) {
foreach ($comment_group as $comment) {
$inline = $this->buildInlineComment(
$comment,
$on_right = true);
$html_new[] = $this->getRowScaffoldForInline($inline);
}
}
if (!$old) {
$th_old = phutil_tag('th', array());
} else {
$th_old = phutil_tag('th', array('id' => "C{$vs}OL1"), 1);
}
if (!$new) {
$th_new = phutil_tag('th', array());
} else {
$th_new = phutil_tag('th', array('id' => "C{$id}NL1"), 1);
}
$output = hsprintf(
'<tr class="differential-image-diff">'.
'%s'.
'<td class="differential-old-image">%s</td>'.
'%s'.
'<td class="differential-new-image" colspan="3">%s</td>'.
'</tr>'.
'%s'.
'%s',
$th_old,
$old,
$th_new,
$new,
phutil_implode_html('', $html_old),
phutil_implode_html('', $html_new));
$output = $this->wrapChangeInTable($output);
return $this->renderChangesetTable($output);
}
public function getRowScaffoldForInline(PHUIDiffInlineCommentView $view) {
return id(new PHUIDiffTwoUpInlineCommentRowScaffold())
->addInlineView($view);
}
private function getNewLineToOffsetMap() {
if ($this->newOffsetMap === null) {
$new = $this->getNewLines();
$map = array();
foreach ($new as $offset => $new_line) {
if ($new_line['line'] === null) {
continue;
}
$map[$new_line['line']] = $offset;
}
$this->newOffsetMap = $map;
}
return $this->newOffsetMap;
}
protected function getTableSigils() {
return array(
'intercept-copy',
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 22:25 (6 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1129379
Default Alt Text
(33 KB)

Event Timeline