mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Add ArcanistLintSeverity::SEVERITY_AUTOFIX.
Summary: Xcode (a popular code editor on Mac OS X) has no facility to trim trailing whitespace automatically. This adds a new lint severity "AUTOFIX" that's between WARNING and ERROR. When running the linter, any lint message whose severity is AUTOFIX will automatically be patched. Furthermore, if all lint messages returned from the engine are AUTOFIX, we'll automatically amend HEAD with the patch. Test Plan: arc lint on files with and without trailing whitespace, with and without UTF-8 contents to confirm those still error Reviewers: epriestley, jungejason Reviewed By: epriestley CC: aran Differential Revision: https://secure.phabricator.com/D2125
This commit is contained in:
parent
55dce2beeb
commit
14d49d2565
7 changed files with 114 additions and 10 deletions
|
@ -49,6 +49,7 @@ final class ArcanistTextLinter extends ArcanistLinter {
|
|||
public function getLintSeverityMap() {
|
||||
return array(
|
||||
self::LINT_LINE_WRAP => ArcanistLintSeverity::SEVERITY_WARNING,
|
||||
self::LINT_TRAILING_WHITESPACE => ArcanistLintSeverity::SEVERITY_AUTOFIX,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,10 @@ final class ArcanistLintMessage {
|
|||
return $this->getSeverity() == ArcanistLintSeverity::SEVERITY_WARNING;
|
||||
}
|
||||
|
||||
public function isAutofix() {
|
||||
return $this->getSeverity() == ArcanistLintSeverity::SEVERITY_AUTOFIX;
|
||||
}
|
||||
|
||||
public function hasFileContext() {
|
||||
return ($this->getLine() !== null);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
* @group lint
|
||||
*/
|
||||
final class ArcanistLintRenderer {
|
||||
private $showAutofixPatches = false;
|
||||
|
||||
public function setShowAutofixPatches($show_autofix_patches) {
|
||||
$this->showAutofixPatches = $show_autofix_patches;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function renderLintResult(ArcanistLintResult $result) {
|
||||
$messages = $result->getMessages();
|
||||
$path = $result->getPath();
|
||||
|
@ -29,9 +36,12 @@ final class ArcanistLintRenderer {
|
|||
$lines = explode("\n", $result->getData());
|
||||
|
||||
$text = array();
|
||||
$text[] = phutil_console_format('**>>>** Lint for __%s__:', $path);
|
||||
$text[] = null;
|
||||
|
||||
foreach ($messages as $message) {
|
||||
if (!$this->showAutofixPatches && $message->isAutofix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($message->isError()) {
|
||||
$color = 'red';
|
||||
} else {
|
||||
|
@ -55,10 +65,13 @@ final class ArcanistLintRenderer {
|
|||
$text[] = $this->renderContext($message, $lines);
|
||||
}
|
||||
}
|
||||
$text[] = null;
|
||||
$text[] = null;
|
||||
|
||||
return implode("\n", $text);
|
||||
if ($text) {
|
||||
$prefix = phutil_console_format("**>>>** Lint for __%s__:\n\n\n", $path);
|
||||
return $prefix . implode("\n", $text);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderContext(
|
||||
|
|
|
@ -79,6 +79,15 @@ final class ArcanistLintResult {
|
|||
return false;
|
||||
}
|
||||
|
||||
public function isAllAutofix() {
|
||||
foreach ($this->messages as $message) {
|
||||
if (!$message->isAutofix()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function sortAndFilterMessages() {
|
||||
$messages = $this->messages;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
final class ArcanistLintSeverity {
|
||||
|
||||
const SEVERITY_ADVICE = 'advice';
|
||||
const SEVERITY_AUTOFIX = 'autofix';
|
||||
const SEVERITY_WARNING = 'warning';
|
||||
const SEVERITY_ERROR = 'error';
|
||||
const SEVERITY_DISABLED = 'disabled';
|
||||
|
@ -31,6 +32,7 @@ final class ArcanistLintSeverity {
|
|||
public static function getStringForSeverity($severity_code) {
|
||||
static $map = array(
|
||||
self::SEVERITY_ADVICE => 'Advice',
|
||||
self::SEVERITY_AUTOFIX => 'Auto-Fix',
|
||||
self::SEVERITY_WARNING => 'Warning',
|
||||
self::SEVERITY_ERROR => 'Error',
|
||||
self::SEVERITY_DISABLED => 'Disabled',
|
||||
|
@ -50,6 +52,7 @@ final class ArcanistLintSeverity {
|
|||
static $map = array(
|
||||
self::SEVERITY_DISABLED => 10,
|
||||
self::SEVERITY_ADVICE => 20,
|
||||
self::SEVERITY_AUTOFIX => 25,
|
||||
self::SEVERITY_WARNING => 30,
|
||||
self::SEVERITY_ERROR => 40,
|
||||
);
|
||||
|
|
|
@ -276,6 +276,22 @@ EOTEXT
|
|||
'lint' => true,
|
||||
),
|
||||
),
|
||||
'amend-all' => array(
|
||||
'help' =>
|
||||
'When linting git repositories, amend HEAD with all patches '.
|
||||
'suggested by lint without prompting.',
|
||||
'passthru' => array(
|
||||
'lint' => true,
|
||||
),
|
||||
),
|
||||
'amend-autofixes' => array(
|
||||
'help' =>
|
||||
'When linting git repositories, amend HEAD with autofix '.
|
||||
'patches suggested by lint without prompting.',
|
||||
'passthru' => array(
|
||||
'lint' => true,
|
||||
),
|
||||
),
|
||||
'json' => array(
|
||||
'help' =>
|
||||
'Emit machine-readable JSON. EXPERIMENTAL! Probably does not work!',
|
||||
|
|
|
@ -30,12 +30,24 @@ class ArcanistLintWorkflow extends ArcanistBaseWorkflow {
|
|||
|
||||
private $unresolvedMessages;
|
||||
private $shouldAmendChanges = false;
|
||||
private $shouldAmendWithoutPrompt = false;
|
||||
private $shouldAmendAutofixesWithoutPrompt = false;
|
||||
|
||||
public function setShouldAmendChanges($should_amend) {
|
||||
$this->shouldAmendChanges = $should_amend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShouldAmendWithoutPrompt($should_amend) {
|
||||
$this->shouldAmendWithoutPrompt = $should_amend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShouldAmendAutofixesWithoutPrompt($should_amend) {
|
||||
$this->shouldAmendAutofixesWithoutPrompt = $should_amend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCommandSynopses() {
|
||||
return phutil_console_format(<<<EOTEXT
|
||||
**lint** [__options__] [__paths__]
|
||||
|
@ -100,6 +112,16 @@ EOTEXT
|
|||
'apply-patches' => true,
|
||||
),
|
||||
),
|
||||
'amend-all' => array(
|
||||
'help' =>
|
||||
'When linting git repositories, amend HEAD with all patches '.
|
||||
'suggested by lint without prompting.',
|
||||
),
|
||||
'amend-autofixes' => array(
|
||||
'help' =>
|
||||
'When linting git repositories, amend HEAD with autofix '.
|
||||
'patches suggested by lint without prompting.',
|
||||
),
|
||||
'*' => 'paths',
|
||||
);
|
||||
}
|
||||
|
@ -155,7 +177,7 @@ EOTEXT
|
|||
if ($this->getArgument('advice')) {
|
||||
$engine->setMinimumSeverity(ArcanistLintSeverity::SEVERITY_ADVICE);
|
||||
} else {
|
||||
$engine->setMinimumSeverity(ArcanistLintSeverity::SEVERITY_WARNING);
|
||||
$engine->setMinimumSeverity(ArcanistLintSeverity::SEVERITY_AUTOFIX);
|
||||
}
|
||||
|
||||
// Propagate information about which lines changed to the lint engine.
|
||||
|
@ -186,6 +208,19 @@ EOTEXT
|
|||
$prompt_patches = true;
|
||||
}
|
||||
|
||||
if ($this->getArgument('amend-all')) {
|
||||
$this->shouldAmendChanges = true;
|
||||
$this->shouldAmendWithoutPrompt = true;
|
||||
}
|
||||
|
||||
if ($this->getArgument('amend-autofixes')) {
|
||||
$prompt_autofix_patches = false;
|
||||
$this->shouldAmendChanges = true;
|
||||
$this->shouldAmendAutofixesWithoutPrompt = true;
|
||||
} else {
|
||||
$prompt_autofix_patches = true;
|
||||
}
|
||||
|
||||
$wrote_to_disk = false;
|
||||
|
||||
switch ($this->getArgument('output')) {
|
||||
|
@ -204,22 +239,35 @@ EOTEXT
|
|||
break;
|
||||
default:
|
||||
$renderer = new ArcanistLintRenderer();
|
||||
$renderer->setShowAutofixPatches($prompt_autofix_patches);
|
||||
break;
|
||||
}
|
||||
|
||||
$all_autofix = true;
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (!$result->getMessages()) {
|
||||
$result_all_autofix = $result->isAllAutofix();
|
||||
|
||||
if (!$result->getMessages() && !$result_all_autofix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
echo $renderer->renderLintResult($result);
|
||||
if (!$result_all_autofix) {
|
||||
$all_autofix = false;
|
||||
}
|
||||
|
||||
$lint_result = $renderer->renderLintResult($result);
|
||||
if ($lint_result) {
|
||||
echo $lint_result;
|
||||
}
|
||||
|
||||
if ($apply_patches && $result->isPatchable()) {
|
||||
$patcher = ArcanistLintPatcher::newFromArcanistLintResult($result);
|
||||
$old = $patcher->getUnmodifiedFileContent();
|
||||
$new = $patcher->getModifiedFileContent();
|
||||
|
||||
if ($prompt_patches) {
|
||||
if ($prompt_patches &&
|
||||
!($result_all_autofix && !$prompt_autofix_patches)) {
|
||||
$old_file = $result->getFilePathOnDisk();
|
||||
if (!Filesystem::pathExists($old_file)) {
|
||||
$old_file = '/dev/null';
|
||||
|
@ -248,7 +296,17 @@ EOTEXT
|
|||
if ($wrote_to_disk &&
|
||||
($repository_api instanceof ArcanistGitAPI) &&
|
||||
$this->shouldAmendChanges) {
|
||||
$amend = phutil_console_confirm("Amend HEAD with lint patches?");
|
||||
|
||||
if ($this->shouldAmendWithoutPrompt ||
|
||||
($this->shouldAmendAutofixesWithoutPrompt && $all_autofix)) {
|
||||
echo phutil_console_format(
|
||||
"<bg:yellow>** LINT NOTICE **</bg> Automatically amending HEAD ".
|
||||
"with lint patches.\n");
|
||||
$amend = true;
|
||||
} else {
|
||||
$amend = phutil_console_confirm("Amend HEAD with lint patches?");
|
||||
}
|
||||
|
||||
if ($amend) {
|
||||
execx(
|
||||
'(cd %s; git commit -a --amend -C HEAD)',
|
||||
|
|
Loading…
Reference in a new issue