mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
Restore coverage reporting to Diffusion browse UI
Summary: Depends on D19377. Ref T13125. Ref T13124. Ref T13105. Coverage reporting in Diffusion didn't initially survive the transition to Document Engine; restore it. This adds some tentative/theoretical support for multiple columns of coverage, but no way to actually produce them in the UI. For now, the labels, codes, and colors are hard coded. Test Plan: Added coverage with `diffusion.updatecoverage`, saw coverage in the UI: {F5525542} Hovered over coverage, got labels and highlighting. Double-checked labels for "N" (Not Executable) and "U" (Uncovered). See PHI577. Faked some multi-column coverage, but you can't currently get this yourself today: {F5525544} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13125, T13124, T13105 Differential Revision: https://secure.phabricator.com/D19378
This commit is contained in:
parent
21bb0215db
commit
665529ab60
10 changed files with 159 additions and 15 deletions
|
@ -119,7 +119,7 @@ return array(
|
||||||
'rsrc/css/font/font-lato.css' => 'c7ccd872',
|
'rsrc/css/font/font-lato.css' => 'c7ccd872',
|
||||||
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
|
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
|
||||||
'rsrc/css/layout/phabricator-filetree-view.css' => 'b912ad97',
|
'rsrc/css/layout/phabricator-filetree-view.css' => 'b912ad97',
|
||||||
'rsrc/css/layout/phabricator-source-code-view.css' => '09368218',
|
'rsrc/css/layout/phabricator-source-code-view.css' => 'fdbefca0',
|
||||||
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
||||||
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
|
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
|
||||||
'rsrc/css/phui/button/phui-button.css' => '1863cc6e',
|
'rsrc/css/phui/button/phui-button.css' => '1863cc6e',
|
||||||
|
@ -388,7 +388,7 @@ return array(
|
||||||
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
||||||
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '1db13e70',
|
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '1db13e70',
|
||||||
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
|
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
|
||||||
'rsrc/js/application/files/behavior-document-engine.js' => '0333c0b6',
|
'rsrc/js/application/files/behavior-document-engine.js' => 'ee0deff8',
|
||||||
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
|
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
|
||||||
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
||||||
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
|
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
|
||||||
|
@ -600,7 +600,7 @@ return array(
|
||||||
'javelin-behavior-diffusion-commit-graph' => '75b83cbb',
|
'javelin-behavior-diffusion-commit-graph' => '75b83cbb',
|
||||||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
||||||
'javelin-behavior-document-engine' => '0333c0b6',
|
'javelin-behavior-document-engine' => 'ee0deff8',
|
||||||
'javelin-behavior-doorkeeper-tag' => '1db13e70',
|
'javelin-behavior-doorkeeper-tag' => '1db13e70',
|
||||||
'javelin-behavior-drydock-live-operation-status' => '901935ef',
|
'javelin-behavior-drydock-live-operation-status' => '901935ef',
|
||||||
'javelin-behavior-durable-column' => '2ae077e1',
|
'javelin-behavior-durable-column' => '2ae077e1',
|
||||||
|
@ -776,7 +776,7 @@ return array(
|
||||||
'phabricator-search-results-css' => '505dd8cf',
|
'phabricator-search-results-css' => '505dd8cf',
|
||||||
'phabricator-shaped-request' => '7cbe244b',
|
'phabricator-shaped-request' => '7cbe244b',
|
||||||
'phabricator-slowvote-css' => 'a94b7230',
|
'phabricator-slowvote-css' => 'a94b7230',
|
||||||
'phabricator-source-code-view-css' => '09368218',
|
'phabricator-source-code-view-css' => 'fdbefca0',
|
||||||
'phabricator-standard-page-view' => '34ee718b',
|
'phabricator-standard-page-view' => '34ee718b',
|
||||||
'phabricator-textareautils' => '320810c8',
|
'phabricator-textareautils' => '320810c8',
|
||||||
'phabricator-title' => '485aaa6c',
|
'phabricator-title' => '485aaa6c',
|
||||||
|
@ -905,11 +905,6 @@ return array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
),
|
),
|
||||||
'0333c0b6' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-stratcom',
|
|
||||||
),
|
|
||||||
'040fce04' => array(
|
'040fce04' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-request',
|
'javelin-request',
|
||||||
|
@ -2110,6 +2105,11 @@ return array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
),
|
),
|
||||||
|
'ee0deff8' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-stratcom',
|
||||||
|
),
|
||||||
'efe49472' => array(
|
'efe49472' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
|
|
|
@ -4,7 +4,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
|
|
||||||
private $lintCommit;
|
private $lintCommit;
|
||||||
private $lintMessages;
|
private $lintMessages;
|
||||||
private $coverage;
|
|
||||||
private $corpusButtons = array();
|
private $corpusButtons = array();
|
||||||
|
|
||||||
public function shouldAllowPublic() {
|
public function shouldAllowPublic() {
|
||||||
|
@ -182,7 +181,6 @@ final class DiffusionBrowseController extends DiffusionController {
|
||||||
|
|
||||||
$corpus = $this->buildGitLFSCorpus($lfs_ref);
|
$corpus = $this->buildGitLFSCorpus($lfs_ref);
|
||||||
} else {
|
} else {
|
||||||
$this->coverage = $drequest->loadCoverage();
|
|
||||||
$show_editor = true;
|
$show_editor = true;
|
||||||
|
|
||||||
$ref = id(new PhabricatorDocumentRef())
|
$ref = id(new PhabricatorDocumentRef())
|
||||||
|
|
|
@ -81,6 +81,11 @@ final class DiffusionDocumentRenderingEngine
|
||||||
$ref
|
$ref
|
||||||
->setSymbolMetadata($this->getSymbolMetadata())
|
->setSymbolMetadata($this->getSymbolMetadata())
|
||||||
->setBlameURI($blame_uri);
|
->setBlameURI($blame_uri);
|
||||||
|
|
||||||
|
$coverage = $drequest->loadCoverage();
|
||||||
|
if (strlen($coverage)) {
|
||||||
|
$ref->addCoverage($coverage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getSymbolMetadata() {
|
private function getSymbolMetadata() {
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class PhabricatorDocumentRef
|
||||||
private $snippet;
|
private $snippet;
|
||||||
private $symbolMetadata = array();
|
private $symbolMetadata = array();
|
||||||
private $blameURI;
|
private $blameURI;
|
||||||
|
private $coverage = array();
|
||||||
|
|
||||||
public function setFile(PhabricatorFile $file) {
|
public function setFile(PhabricatorFile $file) {
|
||||||
$this->file = $file;
|
$this->file = $file;
|
||||||
|
@ -151,4 +152,15 @@ final class PhabricatorDocumentRef
|
||||||
return $this->blameURI;
|
return $this->blameURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addCoverage($coverage) {
|
||||||
|
$this->coverage[] = array(
|
||||||
|
'data' => $coverage,
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCoverage() {
|
||||||
|
return $this->coverage;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ final class PhabricatorSourceDocumentEngine
|
||||||
$options['blame'] = $blame;
|
$options['blame'] = $blame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($ref->getCoverage()) {
|
||||||
|
$options['coverage'] = $ref->getCoverage();
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
$messages,
|
$messages,
|
||||||
$this->newTextDocumentContent($ref, $content, $options),
|
$this->newTextDocumentContent($ref, $content, $options),
|
||||||
|
|
|
@ -22,6 +22,7 @@ abstract class PhabricatorTextDocumentEngine
|
||||||
$options,
|
$options,
|
||||||
array(
|
array(
|
||||||
'blame' => 'optional wild',
|
'blame' => 'optional wild',
|
||||||
|
'coverage' => 'optional list<wild>',
|
||||||
));
|
));
|
||||||
|
|
||||||
if (is_array($content)) {
|
if (is_array($content)) {
|
||||||
|
@ -40,6 +41,11 @@ abstract class PhabricatorTextDocumentEngine
|
||||||
$view->setBlameMap($blame);
|
$view->setBlameMap($blame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$coverage = idx($options, 'coverage');
|
||||||
|
if ($coverage !== null) {
|
||||||
|
$view->setCoverage($coverage);
|
||||||
|
}
|
||||||
|
|
||||||
$message = null;
|
$message = null;
|
||||||
if ($this->encodingMessage !== null) {
|
if ($this->encodingMessage !== null) {
|
||||||
$message = $this->newMessage($this->encodingMessage);
|
$message = $this->newMessage($this->encodingMessage);
|
||||||
|
|
|
@ -145,6 +145,17 @@ abstract class PhabricatorDocumentRenderingEngine
|
||||||
'uri' => $ref->getBlameURI(),
|
'uri' => $ref->getBlameURI(),
|
||||||
'value' => null,
|
'value' => null,
|
||||||
),
|
),
|
||||||
|
'coverage' => array(
|
||||||
|
'labels' => array(
|
||||||
|
// TODO: Modularize this properly, see T13125.
|
||||||
|
array(
|
||||||
|
'C' => pht('Covered'),
|
||||||
|
'U' => pht('Not Covered'),
|
||||||
|
'N' => pht('Not Executable'),
|
||||||
|
'X' => pht('Not Reachable'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$view_button = id(new PHUIButtonView())
|
$view_button = id(new PHUIButtonView())
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
private $truncatedFirstLines = false;
|
private $truncatedFirstLines = false;
|
||||||
private $symbolMetadata;
|
private $symbolMetadata;
|
||||||
private $blameMap;
|
private $blameMap;
|
||||||
|
private $coverage = array();
|
||||||
|
|
||||||
public function setLines(array $lines) {
|
public function setLines(array $lines) {
|
||||||
$this->lines = $lines;
|
$this->lines = $lines;
|
||||||
|
@ -59,6 +60,15 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
return $this->blameMap;
|
return $this->blameMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCoverage(array $coverage) {
|
||||||
|
$this->coverage = $coverage;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCoverage() {
|
||||||
|
return $this->coverage;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
$blame_map = $this->getBlameMap();
|
$blame_map = $this->getBlameMap();
|
||||||
$has_blame = ($blame_map !== null);
|
$has_blame = ($blame_map !== null);
|
||||||
|
@ -97,6 +107,19 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
|
|
||||||
$base_uri = (string)$this->uri;
|
$base_uri = (string)$this->uri;
|
||||||
$wrote_anchor = false;
|
$wrote_anchor = false;
|
||||||
|
|
||||||
|
$coverage = $this->getCoverage();
|
||||||
|
$coverage_count = count($coverage);
|
||||||
|
$coverage_data = ipull($coverage, 'data');
|
||||||
|
|
||||||
|
// TODO: Modularize this properly, see T13125.
|
||||||
|
$coverage_map = array(
|
||||||
|
'C' => 'background: #66bbff;',
|
||||||
|
'U' => 'background: #dd8866;',
|
||||||
|
'N' => 'background: #ddeeff;',
|
||||||
|
'X' => 'background: #aa00aa;',
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($lines as $line) {
|
foreach ($lines as $line) {
|
||||||
$row_attributes = array();
|
$row_attributes = array();
|
||||||
if (isset($this->highlights[$line_number])) {
|
if (isset($this->highlights[$line_number])) {
|
||||||
|
@ -157,6 +180,25 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
$blame_cells = null;
|
$blame_cells = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$coverage_cells = array();
|
||||||
|
foreach ($coverage as $coverage_idx => $coverage_spec) {
|
||||||
|
if (isset($coverage_spec['data'][$line_number - 1])) {
|
||||||
|
$coverage_char = $coverage_spec['data'][$line_number - 1];
|
||||||
|
} else {
|
||||||
|
$coverage_char = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$coverage_style = idx($coverage_map, $coverage_char, null);
|
||||||
|
|
||||||
|
$coverage_cells[] = phutil_tag(
|
||||||
|
'th',
|
||||||
|
array(
|
||||||
|
'class' => 'phabricator-source-coverage',
|
||||||
|
'style' => $coverage_style,
|
||||||
|
'data-coverage' => $coverage_idx.'/'.$coverage_char,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$rows[] = phutil_tag(
|
$rows[] = phutil_tag(
|
||||||
'tr',
|
'tr',
|
||||||
$row_attributes,
|
$row_attributes,
|
||||||
|
@ -174,6 +216,7 @@ final class PhabricatorSourceCodeView extends AphrontView {
|
||||||
'class' => 'phabricator-source-code',
|
'class' => 'phabricator-source-code',
|
||||||
),
|
),
|
||||||
$line),
|
$line),
|
||||||
|
$coverage_cells,
|
||||||
));
|
));
|
||||||
|
|
||||||
$line_number++;
|
$line_number++;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
border: 1px solid {$paste.border};
|
border: 1px solid {$paste.border};
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.phui-oi .phabricator-source-code-container {
|
.phui-oi .phabricator-source-code-container {
|
||||||
|
@ -47,10 +46,12 @@ th.phabricator-source-line a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.phabricator-source-coverage-highlight .phabricator-source-code,
|
||||||
.phabricator-source-highlight .phabricator-source-code {
|
.phabricator-source-highlight .phabricator-source-code {
|
||||||
background: {$paste.highlight};
|
background: {$paste.highlight};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.phabricator-source-coverage-highlight .phabricator-source-line,
|
||||||
.phabricator-source-highlight .phabricator-source-line {
|
.phabricator-source-highlight .phabricator-source-line {
|
||||||
background: {$paste.border};
|
background: {$paste.border};
|
||||||
}
|
}
|
||||||
|
@ -96,7 +97,7 @@ th.phabricator-source-line a:hover {
|
||||||
|
|
||||||
.phabricator-source-blame-info a {
|
.phabricator-source-blame-info a {
|
||||||
color: {$darkbluetext};
|
color: {$darkbluetext};
|
||||||
text-shadow: 1px 1px rgba(0, 0, 0, 0.111);
|
text-shadow: 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.phabricator-source-blame-skip a {
|
.phabricator-source-blame-skip a {
|
||||||
|
@ -123,3 +124,10 @@ th.phabricator-source-line a:hover {
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
th.phabricator-source-coverage {
|
||||||
|
padding: 0 8px;
|
||||||
|
border-left: 1px solid {$thinblueborder};
|
||||||
|
background: {$lightgreybackground};
|
||||||
|
cursor: w-resize;
|
||||||
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ JX.behavior('document-engine', function(config, statics) {
|
||||||
var h_max = 0.44;
|
var h_max = 0.44;
|
||||||
var h = h_min + ((h_max - h_min) * epoch_value);
|
var h = h_min + ((h_max - h_min) * epoch_value);
|
||||||
|
|
||||||
var s = 0.44;
|
var s = 0.25;
|
||||||
|
|
||||||
var v_min = 0.92;
|
var v_min = 0.92;
|
||||||
var v_max = 1.00;
|
var v_max = 1.00;
|
||||||
|
@ -357,6 +357,57 @@ JX.behavior('document-engine', function(config, statics) {
|
||||||
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
|
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onhovercoverage(data, e) {
|
||||||
|
if (e.getType() === 'mouseout') {
|
||||||
|
redraw_coverage(data, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = e.getNode('tag:th');
|
||||||
|
var coverage = target.getAttribute('data-coverage');
|
||||||
|
if (!coverage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw_coverage(data, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
var coverage_row = null;
|
||||||
|
function redraw_coverage(data, node) {
|
||||||
|
if (coverage_row) {
|
||||||
|
JX.DOM.alterClass(
|
||||||
|
coverage_row,
|
||||||
|
'phabricator-source-coverage-highlight',
|
||||||
|
false);
|
||||||
|
coverage_row = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
JX.Tooltip.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var coverage = node.getAttribute('data-coverage');
|
||||||
|
coverage = coverage.split('/');
|
||||||
|
|
||||||
|
var idx = parseInt(coverage[0], 10);
|
||||||
|
var chr = coverage[1];
|
||||||
|
|
||||||
|
var map = data.coverage.labels[idx];
|
||||||
|
if (map) {
|
||||||
|
var label = map[chr];
|
||||||
|
if (label) {
|
||||||
|
JX.Tooltip.show(node, 300, 'W', label);
|
||||||
|
|
||||||
|
coverage_row = JX.DOM.findAbove(node, 'tr');
|
||||||
|
JX.DOM.alterClass(
|
||||||
|
coverage_row,
|
||||||
|
'phabricator-source-coverage-highlight',
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!statics.initialized) {
|
if (!statics.initialized) {
|
||||||
JX.Stratcom.listen('click', 'document-engine-view-dropdown', onmenu);
|
JX.Stratcom.listen('click', 'document-engine-view-dropdown', onmenu);
|
||||||
statics.initialized = true;
|
statics.initialized = true;
|
||||||
|
@ -374,6 +425,12 @@ JX.behavior('document-engine', function(config, statics) {
|
||||||
blame(data);
|
blame(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JX.DOM.listen(
|
||||||
|
JX.$(data.viewportID),
|
||||||
|
['mouseover', 'mouseout'],
|
||||||
|
'tag:th',
|
||||||
|
JX.bind(null, onhovercoverage, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue