Changeset View
Changeset View
Standalone View
Standalone View
src/lint/linter/ArcanistCheckstyleLinter.php
- This file was added.
| <?php | |||||
| class ArcanistCheckstyleLinter extends ArcanistExternalLinter { | |||||
| public function getInfoName() { | |||||
| return 'Java checkstyle linter'; | |||||
| } | |||||
| public function getLinterName() { | |||||
| return 'CHECKSTYLE'; | |||||
| } | |||||
| public function getInfoURI() { | |||||
| return 'http://checkstyle.sourceforge.net'; | |||||
| } | |||||
| public function getInfoDescription() { | |||||
| return pht('Use `%s` to perform static analysis on Java code.', | |||||
| 'checkstyle'); | |||||
| } | |||||
| public function getLinterConfigurationName() { | |||||
| return 'checkstyle'; | |||||
| } | |||||
| public function getVersion() { | |||||
| list($stdout) = execx('%C -v', $this->getExecutableCommand()); | |||||
| $matches = array(); | |||||
| $regex = '/^Checkstyle version: (?P<version>\d+\.\d+)$/'; | |||||
| if (preg_match($regex, $stdout, $matches)) { | |||||
| return $matches['version']; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public function getInstallInstructions() { | |||||
| return pht('Ensure java is configured as interpreter and '. | |||||
| 'the checkstyle jar is configured as the binary. If you need to pass '. | |||||
| 'additional additional JVM arguments include them with the '. | |||||
| '`interpreter` field. Use the `flags` field to configure checkstyle '. | |||||
| 'arguments, including the `-c my_styles.xml` for the styles to verify.'); | |||||
| } | |||||
| protected function getMandatoryFlags() { | |||||
| return array('-f', 'xml'); | |||||
| } | |||||
| public function shouldExpectCommandErrors() { | |||||
| return false; | |||||
| } | |||||
| public function shouldUseInterpreter() { | |||||
| return true; | |||||
| } | |||||
| public function getDefaultInterpreter() { | |||||
| return 'java'; | |||||
| } | |||||
| public function getDefaultBinary() { | |||||
| return 'checkstyle.jar'; | |||||
| } | |||||
| protected function parseLinterOutput($path, $err, $stdout, $stderr) { | |||||
| $dom = new DOMDocument(); | |||||
| $ok = @$dom->loadXML($stdout); | |||||
| if (!$ok) { | |||||
| return false; | |||||
| } | |||||
| $files = $dom->getElementsByTagName('file'); | |||||
| $messages = array(); | |||||
| foreach ($files as $file) { | |||||
| $errors = $file->getElementsByTagName('error'); | |||||
| foreach ($errors as $error) { | |||||
| $message = new ArcanistLintMessage(); | |||||
| $message->setPath($file->getAttribute('name')); | |||||
| $message->setLine($error->getAttribute('line')); | |||||
| $message->setCode($this->getLinterName()); | |||||
| // source is the module's fully-qualified classname | |||||
| // attempt to simplify it for readability | |||||
| $source = $error->getAttribute('source'); | |||||
| $simple_classname_matches = array(); | |||||
| $simple_classname_regex = '/.*\.(<simplename>)$/'; | |||||
| if (preg_match($simple_classname_regex, $source, | |||||
| $simple_classname_matches)) { | |||||
| $source = $simple_classname_matches['simplename']; | |||||
| } | |||||
| $message->setName($source); | |||||
| // checkstyle's XMLLogger escapes these five characters | |||||
| $description = $error->getAttribute('message'); | |||||
| $description = str_replace( | |||||
| ['<', '>', ''', '"', '&'], | |||||
| ['<', '>', '\'', '"', '&'], | |||||
| $description); | |||||
| $message->setDescription($description); | |||||
| $column = $error->getAttribute('column'); | |||||
| if ($column) { | |||||
| $message->setChar($column); | |||||
| } | |||||
| $severity = $error->getAttribute('severity'); | |||||
| switch ($severity) { | |||||
| case 'error': | |||||
| $message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR); | |||||
| break; | |||||
| case 'warning': | |||||
| $message->setSeverity(ArcanistLintSeverity::SEVERITY_WARNING); | |||||
| break; | |||||
| case 'info': | |||||
| $message->setSeverity(ArcanistLintSeverity::SEVERITY_ADVICE); | |||||
| break; | |||||
| case 'ignore': | |||||
| $message->setSeverity(ArcanistLintSeverity::SEVERITY_DISABLED); | |||||
| break; | |||||
| // The above four are the only valid checkstyle severities, | |||||
| // this is for completion as well as preparing for future severities | |||||
| default: | |||||
| $message->setSeverity(ArcanistLintSeverity::SEVERITY_WARNING); | |||||
| break; | |||||
| } | |||||
| $messages[] = $message; | |||||
| } | |||||
| } | |||||
| return $messages; | |||||
| } | |||||
| } | |||||