Changeset View
Changeset View
Standalone View
Standalone View
src/workflow/ArcanistLintWorkflow.php
| Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | return array( | ||||
| 'hg', | 'hg', | ||||
| ), | ), | ||||
| 'nosupport' => array( | 'nosupport' => array( | ||||
| 'svn' => pht('Lint does not currently support %s in SVN.', '--rev'), | 'svn' => pht('Lint does not currently support %s in SVN.', '--rev'), | ||||
| ), | ), | ||||
| ), | ), | ||||
| 'output' => array( | 'output' => array( | ||||
| 'param' => 'format', | 'param' => 'format', | ||||
| 'help' => pht( | 'help' => pht('Select an output format.'), | ||||
| "With 'summary', show lint warnings in a more compact format. ". | |||||
| "With 'json', show lint warnings in machine-readable JSON format. ". | |||||
| "With 'none', show no lint warnings. ". | |||||
| "With 'compiler', show lint warnings in suitable for your editor. ". | |||||
| "With 'xml', show lint warnings in the Checkstyle XML format."), | |||||
| ), | ), | ||||
| 'outfile' => array( | 'outfile' => array( | ||||
| 'param' => 'path', | 'param' => 'path', | ||||
| 'help' => pht( | 'help' => pht( | ||||
| 'Output the linter results to a file. Defaults to stdout.'), | 'Output the linter results to a file. Defaults to stdout.'), | ||||
| ), | ), | ||||
| 'engine' => array( | 'engine' => array( | ||||
| 'param' => 'classname', | 'param' => 'classname', | ||||
| ▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | public function run() { | ||||
| } | } | ||||
| if ($this->getArgument('amend-all')) { | if ($this->getArgument('amend-all')) { | ||||
| $this->shouldAmendChanges = true; | $this->shouldAmendChanges = true; | ||||
| $this->shouldAmendWithoutPrompt = true; | $this->shouldAmendWithoutPrompt = true; | ||||
| } | } | ||||
| if ($this->getArgument('amend-autofixes')) { | if ($this->getArgument('amend-autofixes')) { | ||||
| $prompt_autofix_patches = false; | |||||
| $this->shouldAmendChanges = true; | $this->shouldAmendChanges = true; | ||||
| $this->shouldAmendAutofixesWithoutPrompt = true; | $this->shouldAmendAutofixesWithoutPrompt = true; | ||||
| } else { | |||||
| $prompt_autofix_patches = true; | |||||
| } | } | ||||
| $repository_api = $this->getRepositoryAPI(); | $repository_api = $this->getRepositoryAPI(); | ||||
| if ($this->shouldAmendChanges) { | if ($this->shouldAmendChanges) { | ||||
| $this->shouldAmendChanges = $repository_api->supportsAmend() && | $this->shouldAmendChanges = $repository_api->supportsAmend() && | ||||
| !$this->isHistoryImmutable(); | !$this->isHistoryImmutable(); | ||||
| } | } | ||||
| $wrote_to_disk = false; | $wrote_to_disk = false; | ||||
| switch ($this->getArgument('output')) { | $default_renderer = ArcanistConsoleLintRenderer::RENDERERKEY; | ||||
| case 'json': | $renderer_key = $this->getArgument('output', $default_renderer); | ||||
| $renderer = new ArcanistJSONLintRenderer(); | |||||
| $prompt_patches = false; | $renderers = ArcanistLintRenderer::getAllRenderers(); | ||||
| $apply_patches = $this->getArgument('apply-patches'); | if (!isset($renderers[$renderer_key])) { | ||||
| break; | throw new Exception( | ||||
| case 'summary': | pht( | ||||
| $renderer = new ArcanistSummaryLintRenderer(); | 'Lint renderer "%s" is unknown. Supported renderers are: %s.', | ||||
| break; | $renderer_key, | ||||
| case 'none': | implode(', ', array_keys($renderers)))); | ||||
| $prompt_patches = false; | |||||
| $apply_patches = $this->getArgument('apply-patches'); | |||||
| $renderer = new ArcanistNoneLintRenderer(); | |||||
| break; | |||||
| case 'compiler': | |||||
| $renderer = new ArcanistCompilerLintRenderer(); | |||||
| $prompt_patches = false; | |||||
| $apply_patches = $this->getArgument('apply-patches'); | |||||
| break; | |||||
| case 'xml': | |||||
| $renderer = new ArcanistCheckstyleXMLLintRenderer(); | |||||
| $prompt_patches = false; | |||||
| $apply_patches = $this->getArgument('apply-patches'); | |||||
| break; | |||||
| default: | |||||
| $renderer = new ArcanistConsoleLintRenderer(); | |||||
| $renderer->setShowAutofixPatches($prompt_autofix_patches); | |||||
| break; | |||||
| } | } | ||||
| $renderer = $renderers[$renderer_key]; | |||||
| $all_autofix = true; | $all_autofix = true; | ||||
| $tmp = null; | |||||
| if ($this->getArgument('outfile') !== null) { | $out_path = $this->getArgument('outfile'); | ||||
| $tmp = id(new TempFile()) | if ($out_path !== null) { | ||||
| ->setPreserveFile(true); | $tmp = new TempFile(); | ||||
| $renderer->setOutputPath((string)$tmp); | |||||
| } else { | |||||
| $tmp = null; | |||||
| } | } | ||||
| $preamble = $renderer->renderPreamble(); | if ($failed) { | ||||
| if ($tmp) { | $renderer->handleException($failed); | ||||
| Filesystem::appendFile($tmp, $preamble); | |||||
| } else { | |||||
| $console->writeOut('%s', $preamble); | |||||
| } | } | ||||
| foreach ($results as $result) { | $renderer->willRenderResults(); | ||||
| $result_all_autofix = $result->isAllAutofix(); | |||||
| if (!$result->getMessages() && !$result_all_autofix) { | $should_patch = ($apply_patches && $renderer->supportsPatching()); | ||||
| foreach ($results as $result) { | |||||
| if (!$result->getMessages()) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| $result_all_autofix = $result->isAllAutofix(); | |||||
| if (!$result_all_autofix) { | if (!$result_all_autofix) { | ||||
| $all_autofix = false; | $all_autofix = false; | ||||
| } | } | ||||
| $lint_result = $renderer->renderLintResult($result); | $renderer->renderLintResult($result); | ||||
| if ($lint_result) { | |||||
| if ($tmp) { | |||||
| Filesystem::appendFile($tmp, $lint_result); | |||||
| } else { | |||||
| $console->writeOut('%s', $lint_result); | |||||
| } | |||||
| } | |||||
| if ($apply_patches && $result->isPatchable()) { | if ($should_patch && $result->isPatchable()) { | ||||
| $patcher = ArcanistLintPatcher::newFromArcanistLintResult($result); | $patcher = ArcanistLintPatcher::newFromArcanistLintResult($result); | ||||
| $old_file = $result->getFilePathOnDisk(); | |||||
| if ($prompt_patches && | $apply = true; | ||||
| !($result_all_autofix && !$prompt_autofix_patches)) { | if ($prompt_patches && !$result_all_autofix) { | ||||
| $old_file = $result->getFilePathOnDisk(); | |||||
| if (!Filesystem::pathExists($old_file)) { | if (!Filesystem::pathExists($old_file)) { | ||||
| $old_file = '/dev/null'; | $old_file = null; | ||||
| } | } | ||||
| $new_file = new TempFile(); | $new_file = new TempFile(); | ||||
| $new = $patcher->getModifiedFileContent(); | $new = $patcher->getModifiedFileContent(); | ||||
| Filesystem::writeFile($new_file, $new); | Filesystem::writeFile($new_file, $new); | ||||
| // TODO: Improve the behavior here, make it more like | $apply = $renderer->promptForPatch($result, $old_file, $new_file); | ||||
| // difference_render(). | |||||
| list(, $stdout, $stderr) = | |||||
| exec_manual('diff -u %s %s', $old_file, $new_file); | |||||
| $console->writeOut('%s', $stdout); | |||||
| $console->writeErr('%s', $stderr); | |||||
| $prompt = pht( | |||||
| 'Apply this patch to %s?', | |||||
| phutil_console_format('__%s__', $result->getPath())); | |||||
| if (!phutil_console_confirm($prompt, $default_no = false)) { | |||||
| continue; | |||||
| } | |||||
| } | } | ||||
| if ($apply) { | |||||
| $patcher->writePatchToDisk(); | $patcher->writePatchToDisk(); | ||||
| $wrote_to_disk = true; | $wrote_to_disk = true; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| $renderer->didRenderResults(); | |||||
| $postamble = $renderer->renderPostamble(); | |||||
| if ($tmp) { | if ($tmp) { | ||||
| Filesystem::appendFile($tmp, $postamble); | Filesystem::rename($tmp, $out_path); | ||||
| Filesystem::rename($tmp, $this->getArgument('outfile')); | |||||
| } else { | |||||
| $console->writeOut('%s', $postamble); | |||||
| } | } | ||||
| if ($wrote_to_disk && $this->shouldAmendChanges) { | if ($wrote_to_disk && $this->shouldAmendChanges) { | ||||
| if ($this->shouldAmendWithoutPrompt || | if ($this->shouldAmendWithoutPrompt || | ||||
| ($this->shouldAmendAutofixesWithoutPrompt && $all_autofix)) { | ($this->shouldAmendAutofixesWithoutPrompt && $all_autofix)) { | ||||
| $console->writeOut( | $console->writeOut( | ||||
| "<bg:yellow>** %s **</bg> %s\n", | "<bg:yellow>** %s **</bg> %s\n", | ||||
| pht('LINT NOTICE'), | pht('LINT NOTICE'), | ||||
| Show All 13 Lines | if ($wrote_to_disk && $this->shouldAmendChanges) { | ||||
| } else { | } else { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| pht( | pht( | ||||
| 'Sort out the lint changes that were applied to the working '. | 'Sort out the lint changes that were applied to the working '. | ||||
| 'copy and relint.')); | 'copy and relint.')); | ||||
| } | } | ||||
| } | } | ||||
| if ($this->getArgument('output') == 'json') { | |||||
| // NOTE: Required by save_lint.php in Phabricator. | |||||
| return 0; | |||||
| } | |||||
| if ($failed) { | |||||
| if ($failed instanceof ArcanistNoEffectException) { | |||||
| if ($renderer instanceof ArcanistNoneLintRenderer) { | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| throw $failed; | |||||
| } | |||||
| $unresolved = array(); | $unresolved = array(); | ||||
| $has_warnings = false; | $has_warnings = false; | ||||
| $has_errors = false; | $has_errors = false; | ||||
| foreach ($results as $result) { | foreach ($results as $result) { | ||||
| foreach ($result->getMessages() as $message) { | foreach ($result->getMessages() as $message) { | ||||
| if (!$message->isPatchApplied()) { | if (!$message->isPatchApplied()) { | ||||
| if ($message->isError()) { | if ($message->isError()) { | ||||
| Show All 12 Lines | public function run() { | ||||
| if ($has_errors) { | if ($has_errors) { | ||||
| $result_code = self::RESULT_ERRORS; | $result_code = self::RESULT_ERRORS; | ||||
| } else if ($has_warnings) { | } else if ($has_warnings) { | ||||
| $result_code = self::RESULT_WARNINGS; | $result_code = self::RESULT_WARNINGS; | ||||
| } else { | } else { | ||||
| $result_code = self::RESULT_OKAY; | $result_code = self::RESULT_OKAY; | ||||
| } | } | ||||
| if (!$this->getParentWorkflow()) { | $renderer->renderResultCode($result_code); | ||||
| if ($result_code == self::RESULT_OKAY) { | |||||
| $console->writeOut('%s', $renderer->renderOkayResult()); | |||||
| } | |||||
| } | |||||
| return $result_code; | return $result_code; | ||||
| } | } | ||||
| public function getUnresolvedMessages() { | public function getUnresolvedMessages() { | ||||
| return $this->unresolvedMessages; | return $this->unresolvedMessages; | ||||
| } | } | ||||
| } | } | ||||