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; | |||||
} | |||||
} |