Page MenuHomePhorge

ArcanistPyLintLinter.php
No OneTemporary

ArcanistPyLintLinter.php

<?php
/**
* Uses "PyLint" to detect various errors in Python code.
*/
final class ArcanistPyLintLinter extends ArcanistExternalLinter {
private $config;
public function getInfoName() {
return 'PyLint';
}
public function getInfoURI() {
return 'http://www.pylint.org/';
}
public function getInfoDescription() {
return pht(
'PyLint is a Python source code analyzer which looks for '.
'programming errors, helps enforcing a coding standard and '.
'sniffs for some code smells.');
}
public function getLinterName() {
return 'PyLint';
}
public function getLinterConfigurationName() {
return 'pylint';
}
public function getDefaultBinary() {
return 'pylint';
}
public function getVersion() {
list($stdout) = execx('%C --version', $this->getExecutableCommand());
$matches = array();
$regex = '/^pylint (?P<version>\d+\.\d+\.\d+)/';
if (preg_match($regex, $stdout, $matches)) {
return $matches['version'];
} else {
return false;
}
}
public function getInstallInstructions() {
return pht(
'Install PyLint using `%s`.',
'pip install pylint');
}
public function shouldExpectCommandErrors() {
return true;
}
public function getLinterConfigurationOptions() {
$options = array(
'pylint.config' => array(
'type' => 'optional string',
'help' => pht('Pass in a custom configuration file path.'),
),
);
return $options + parent::getLinterConfigurationOptions();
}
public function setLinterConfigurationValue($key, $value) {
switch ($key) {
case 'pylint.config':
$this->config = $value;
return;
default:
return parent::setLinterConfigurationValue($key, $value);
}
}
protected function getMandatoryFlags() {
$options = array();
$options[] = '--reports=no';
$options[] = '--msg-template={line}|{column}|{msg_id}|{symbol}|{msg}';
// Specify an `--rcfile`, either absolute or relative to the project root.
// Stupidly, the command line args above are overridden by rcfile, so be
// careful.
$config = $this->config;
if ($config !== null) {
$options[] = '--rcfile='.$config;
}
return $options;
}
protected function getDefaultFlags() {
$options = array();
$installed_version = $this->getVersion();
$minimum_version = '1.0.0';
if (version_compare($installed_version, $minimum_version, '<')) {
throw new ArcanistMissingLinterException(
pht(
'%s is not compatible with the installed version of pylint. '.
'Minimum version: %s; installed version: %s.',
__CLASS__,
$minimum_version,
$installed_version));
}
return $options;
}
protected function parseLinterOutput($path, $err, $stdout, $stderr) {
if ($err === 32) {
// According to `man pylint` the exit status of 32 means there was a
// usage error. That's bad, so actually exit abnormally.
return false;
}
$lines = phutil_split_lines($stdout, false);
$messages = array();
foreach ($lines as $line) {
$matches = explode('|', $line, 5);
if (count($matches) < 5) {
continue;
}
// NOTE: PyLint sometimes returns -1 as the character offset for a
// message. If it does, treat it as 0. See T9257.
$char = (int)$matches[1];
$char = max(0, $char);
$message = id(new ArcanistLintMessage())
->setPath($path)
->setLine($matches[0])
->setChar($char)
->setCode($matches[2])
->setSeverity($this->getLintMessageSeverity($matches[2]))
->setName(ucwords(str_replace('-', ' ', $matches[3])))
->setDescription($matches[4]);
$messages[] = $message;
}
return $messages;
}
protected function getDefaultMessageSeverity($code) {
switch (substr($code, 0, 1)) {
case 'R':
case 'C':
return ArcanistLintSeverity::SEVERITY_ADVICE;
case 'W':
return ArcanistLintSeverity::SEVERITY_WARNING;
case 'E':
case 'F':
return ArcanistLintSeverity::SEVERITY_ERROR;
default:
return ArcanistLintSeverity::SEVERITY_DISABLED;
}
}
protected function getLintCodeFromLinterConfigurationKey($code) {
if (!preg_match('/^(R|C|W|E|F)\d{4}$/', $code)) {
throw new Exception(
pht(
'Unrecognized lint message code "%s". Expected a valid Pylint '.
'lint code like "%s", or "%s", or "%s".',
$code,
'C0111',
'E0602',
'W0611'));
}
return $code;
}
}

File Metadata

Mime Type
text/x-php
Expires
Mon, Mar 24, 03:11 (1 d, 2 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1114153
Default Alt Text
ArcanistPyLintLinter.php (4 KB)

Event Timeline