@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.

Add support for postponed linters

Summary:
This adds:
1) A new "arc:lint-postponed" diff property which stores a list of
lint names that are postponed and a finishpostponedlinters conduit
method which removes linters from this list. Postponed linters are
shown in the lint details.
2) A updatelintmessages conduit message, which adds additional lint
messages to the "arc:lint" diff property.

In combination, this provides very basic support for running
asynchronous static analysis tools. When the diff is being created,
a list of asynchronous static analysis runs can be added to the
diff's postponed linters list. As these postponed linters finish
up, then can report new lint messages back to the diff then mark
themselves as complete.

The client is currently responsible for filtering the lint messages
by things like affected lines and files.

Test Plan:
Used conduit call API to add lint messages and remove postponed
linters from a test diff.

Reviewers: epriestley, vrana, nh, jungejason

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T1332

Differential Revision: https://secure.phabricator.com/D2792

+197 -5
+2
src/__phutil_library_map__.php
··· 138 138 'ConduitAPI_differential_createrawdiff_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_createrawdiff_Method.php', 139 139 'ConduitAPI_differential_createrevision_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_createrevision_Method.php', 140 140 'ConduitAPI_differential_find_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_find_Method.php', 141 + 'ConduitAPI_differential_finishpostponedlinters_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_finishpostponedlinters_Method.php', 141 142 'ConduitAPI_differential_getalldiffs_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_getalldiffs_Method.php', 142 143 'ConduitAPI_differential_getcommitmessage_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_getcommitmessage_Method.php', 143 144 'ConduitAPI_differential_getcommitpaths_Method' => 'applications/conduit/method/differential/ConduitAPI_differential_getcommitpaths_Method.php', ··· 1214 1215 'ConduitAPI_differential_createrawdiff_Method' => 'ConduitAPI_differential_Method', 1215 1216 'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod', 1216 1217 'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod', 1218 + 'ConduitAPI_differential_finishpostponedlinters_Method' => 'ConduitAPIMethod', 1217 1219 'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod', 1218 1220 'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod', 1219 1221 'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
+131
src/applications/conduit/method/differential/ConduitAPI_differential_finishpostponedlinters_Method.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + /** 20 + * @group conduit 21 + */ 22 + final class ConduitAPI_differential_finishpostponedlinters_Method 23 + extends ConduitAPIMethod { 24 + 25 + public function getMethodDescription() { 26 + return "Update diff with new lint messages and mark postponed ". 27 + "linters as finished."; 28 + } 29 + 30 + public function defineParamTypes() { 31 + return array( 32 + 'diffID' => 'required diffID', 33 + 'linters' => 'required dict', 34 + ); 35 + } 36 + 37 + public function defineReturnType() { 38 + return 'void'; 39 + } 40 + 41 + public function defineErrorTypes() { 42 + return array( 43 + 'ERR-BAD-DIFF' => 'Bad diff ID.', 44 + 'ERR-BAD-LINTER' => 'No postponed linter by the given name', 45 + 'ERR-NO-LINT' => 'No postponed lint field available in diff', 46 + ); 47 + } 48 + 49 + protected function execute(ConduitAPIRequest $request) { 50 + 51 + $diff_id = $request->getValue('diffID'); 52 + $linter_map = $request->getValue('linters'); 53 + 54 + $diff = id(new DifferentialDiff())->load($diff_id); 55 + if (!$diff) { 56 + throw new ConduitException('ERR-BAD-DIFF'); 57 + } 58 + 59 + // Extract the finished linters and messages from the linter map. 60 + $finished_linters = array_keys($linter_map); 61 + $new_messages = array(); 62 + foreach ($linter_map as $linter => $messages) { 63 + $new_messages = array_merge($new_messages, $messages); 64 + } 65 + 66 + // Load the postponed linters attached to this diff. 67 + $postponed_linters_property = id( 68 + new DifferentialDiffProperty())->loadOneWhere( 69 + 'diffID = %d AND name = %s', 70 + $diff_id, 71 + 'arc:lint-postponed'); 72 + if ($postponed_linters_property) { 73 + $postponed_linters = $postponed_linters_property->getData(); 74 + } else { 75 + $postponed_linters = array(); 76 + } 77 + 78 + foreach ($finished_linters as $linter) { 79 + if (!in_array($linter, $postponed_linters)) { 80 + throw new ConduitException('ERR-BAD-LINTER'); 81 + } 82 + } 83 + 84 + foreach ($postponed_linters as $idx => $linter) { 85 + if (in_array($linter, $finished_linters)) { 86 + unset($postponed_linters[$idx]); 87 + } 88 + } 89 + 90 + // Load the lint messages currenty attached to the diff. If this 91 + // diff property doesn't exist, create it. 92 + $messages_property = id(new DifferentialDiffProperty())->loadOneWhere( 93 + 'diffID = %d AND name = %s', 94 + $diff_id, 95 + 'arc:lint' 96 + ); 97 + if ($messages_property) { 98 + $messages = $messages_property->getData(); 99 + } else { 100 + $messages = array(); 101 + } 102 + 103 + // Add new lint messages, removing duplicates. 104 + foreach ($new_messages as $new_message) { 105 + if (!in_array($new_message, $messages)) { 106 + $messages[] = $new_message; 107 + } 108 + } 109 + 110 + // Use setdiffproperty to update the postponed linters and messages, 111 + // as these will also update the lint status correctly. 112 + $call = new ConduitCall( 113 + 'differential.setdiffproperty', 114 + array( 115 + 'diff_id' => $diff_id, 116 + 'name' => 'arc:lint', 117 + 'data' => json_encode($messages))); 118 + $call->setUser($request->getUser()); 119 + $call->execute(); 120 + $call = new ConduitCall( 121 + 'differential.setdiffproperty', 122 + array( 123 + 'diff_id' => $diff_id, 124 + 'name' => 'arc:lint-postponed', 125 + 'data' => json_encode($postponed_linters))); 126 + $call->setUser($request->getUser()); 127 + $call->execute(); 128 + 129 + } 130 + 131 + }
+30 -3
src/applications/conduit/method/differential/ConduitAPI_differential_setdiffproperty_Method.php
··· 44 44 ); 45 45 } 46 46 47 - private static function updateLintStatus($diff_id, array $results) { 47 + private static function updateLintStatus($diff_id) { 48 + 48 49 $diff = id(new DifferentialDiff())->load($diff_id); 49 50 if (!$diff) { 50 51 throw new ConduitException('ERR_NOT_FOUND'); 51 52 } 52 53 54 + // Load the postponed linters attached to this diff. 55 + $postponed_linters_property = id( 56 + new DifferentialDiffProperty())->loadOneWhere( 57 + 'diffID = %d AND name = %s', 58 + $diff_id, 59 + 'arc:lint-postponed'); 60 + if ($postponed_linters_property) { 61 + $postponed_linters = $postponed_linters_property->getData(); 62 + } else { 63 + $postponed_linters = array(); 64 + } 65 + 66 + // Load the lint messages currenty attached to the diff 67 + $messages_property = id(new DifferentialDiffProperty())->loadOneWhere( 68 + 'diffID = %d AND name = %s', 69 + $diff_id, 70 + 'arc:lint' 71 + ); 72 + if ($messages_property) { 73 + $results = $messages_property->getData(); 74 + } else { 75 + $results = array(); 76 + } 77 + 53 78 $has_error = false; 54 79 $has_warning = false; 55 80 foreach ($results as $result) { ··· 66 91 $diff->setLintStatus(DifferentialLintStatus::LINT_FAIL); 67 92 } else if ($has_warning) { 68 93 $diff->setLintStatus(DifferentialLintStatus::LINT_WARN); 94 + } else if (!empty($postponed_linters)) { 95 + $diff->setLintStatus(DifferentialLintStatus::LINT_POSTPONED); 69 96 } else if ($results && 70 97 $diff->getLintStatus() === DifferentialLintStatus::LINT_NONE) { 71 98 $diff->setLintStatus(DifferentialLintStatus::LINT_OKAY); ··· 80 107 81 108 self::updateDiffProperty($diff_id, $name, $data); 82 109 83 - if ($name === 'arc:lint') { 84 - self::updateLintStatus($diff_id, $data); 110 + if ($name === 'arc:lint' || $name == 'arc:lint-postponed') { 111 + self::updateLintStatus($diff_id); 85 112 } 86 113 87 114 return;
+2 -1
src/applications/differential/constants/DifferentialLintStatus.php
··· 1 1 <?php 2 2 3 3 /* 4 - * Copyright 2011 Facebook, Inc. 4 + * Copyright 2012 Facebook, Inc. 5 5 * 6 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 7 * you may not use this file except in compliance with the License. ··· 23 23 const LINT_WARN = 2; 24 24 const LINT_FAIL = 3; 25 25 const LINT_SKIP = 4; 26 + const LINT_POSTPONED = 5; 26 27 27 28 }
+29 -1
src/applications/differential/field/specification/DifferentialLintFieldSpecification.php
··· 28 28 } 29 29 30 30 public function getRequiredDiffProperties() { 31 - return array('arc:lint', 'arc:lint-excuse'); 31 + return array('arc:lint', 'arc:lint-excuse', 'arc:lint-postponed'); 32 32 } 33 33 34 34 private function getLintExcuse() { 35 35 return $this->getDiffProperty('arc:lint-excuse'); 36 + } 37 + 38 + private function getPostponedLinters() { 39 + return $this->getDiffProperty('arc:lint-postponed'); 36 40 } 37 41 38 42 public function renderValueForRevisionView() { ··· 132 136 } 133 137 } 134 138 139 + $postponed = $this->getPostponedLinters(); 140 + if ($postponed) { 141 + foreach ($postponed as $linter) { 142 + $rows[] = array( 143 + 'style' => $this->getPostponedStyle(), 144 + 'name' => 'Postponed', 145 + 'value' => phutil_escape_html($linter), 146 + 'show' => false, 147 + ); 148 + if (empty($hidden['postponed'])) { 149 + $hidden['postponed'] = 0; 150 + } 151 + $hidden['postponed']++; 152 + } 153 + } 154 + 135 155 $show_string = $this->renderShowString($hidden); 136 156 137 157 $view = new DifferentialResultsTableView(); ··· 151 171 return idx($map, $severity); 152 172 } 153 173 174 + private function getPostponedStyle() { 175 + return 'blue'; 176 + } 177 + 154 178 private function renderShowString(array $hidden) { 155 179 if (!$hidden) { 156 180 return null; ··· 165 189 ArcanistLintSeverity::SEVERITY_AUTOFIX, 166 190 ArcanistLintSeverity::SEVERITY_ADVICE, 167 191 'details', 192 + 'postponed', 168 193 )) + $hidden; 169 194 170 195 $show = array(); ··· 184 209 break; 185 210 case 'details': 186 211 $show[] = pht('%d Detail(s)', $value); 212 + break; 213 + case 'postponed': 214 + $show[] = pht('%d Postponed', $value); 187 215 break; 188 216 default: 189 217 $show[] = $value;
+3
src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php
··· 252 252 DifferentialLintStatus::LINT_WARN => self::STAR_WARN, 253 253 DifferentialLintStatus::LINT_FAIL => self::STAR_FAIL, 254 254 DifferentialLintStatus::LINT_SKIP => self::STAR_SKIP, 255 + DifferentialLintStatus::LINT_POSTPONED => self::STAR_SKIP 255 256 ); 256 257 257 258 $star = idx($map, $diff->getLintStatus(), self::STAR_FAIL); ··· 286 287 return 'Lint Errors'; 287 288 case DifferentialLintStatus::LINT_SKIP: 288 289 return 'Lint Skipped'; 290 + case DifferentialLintStatus::LINT_POSTPONED: 291 + return 'Lint Postponed'; 289 292 } 290 293 return '???'; 291 294 }