2011-01-10 00:22:25 +01:00
|
|
|
<?php
|
|
|
|
|
2011-02-19 20:36:08 +01:00
|
|
|
/**
|
|
|
|
* Implements lint rules, like syntax checks for a specific language.
|
|
|
|
*
|
|
|
|
* @group linter
|
2012-01-31 21:07:05 +01:00
|
|
|
* @stable
|
2011-02-19 20:36:08 +01:00
|
|
|
*/
|
2011-01-10 00:22:25 +01:00
|
|
|
abstract class ArcanistLinter {
|
|
|
|
|
2012-11-22 03:38:24 +01:00
|
|
|
const GRANULARITY_FILE = 1;
|
|
|
|
const GRANULARITY_DIRECTORY = 2;
|
|
|
|
const GRANULARITY_REPOSITORY = 3;
|
|
|
|
const GRANULARITY_GLOBAL = 4;
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
protected $paths = array();
|
|
|
|
protected $data = array();
|
|
|
|
protected $engine;
|
|
|
|
protected $activePath;
|
|
|
|
protected $messages = array();
|
|
|
|
|
|
|
|
protected $stopAllLinters = false;
|
|
|
|
|
|
|
|
private $customSeverityMap = array();
|
2012-11-06 00:58:24 +01:00
|
|
|
private $config = array();
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
public function setCustomSeverityMap(array $map) {
|
|
|
|
$this->customSeverityMap = $map;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-11-06 00:58:24 +01:00
|
|
|
public function setConfig(array $config) {
|
|
|
|
$this->config = $config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getConfig($key, $default = null) {
|
|
|
|
return idx($this->config, $key, $default);
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
public function getActivePath() {
|
|
|
|
return $this->activePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function stopAllLinters() {
|
|
|
|
$this->stopAllLinters = true;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function didStopAllLinters() {
|
|
|
|
return $this->stopAllLinters;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPath($path) {
|
|
|
|
$this->paths[$path] = $path;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-10-20 14:45:22 +02:00
|
|
|
public function setPaths(array $paths) {
|
|
|
|
$this->paths = $paths;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
public function getPaths() {
|
|
|
|
return array_values($this->paths);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addData($path, $data) {
|
|
|
|
$this->data[$path] = $data;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getData($path) {
|
|
|
|
if (!array_key_exists($path, $this->data)) {
|
[arc svn-hook-pre-commit] Access working copy
Summary:
Creates a new hook API that can be used to interface with
SVN/Git/Mercurial in the context of a commit hook. Currently only adds a
function to read the modified file data in a Subversion commit hook.
An object of this API is created in the SvnHookPreCommitWorkflow and
passed on the Lint Engine which then uses it to access current file
data, of the way the APIs seem to be structured); linters use the
getData function which is essentially a wrapper around the engine's
call, with another layer of caching.
Task ID: #770556
Blame Rev:
Test Plan:
- Create a local svn repository and add a minimal hook to run the local
version of arc to test commits
(http://phabricator.com/docs/arcanist/article/Installing_Arcanist_SVN_Hooks.html)
- Create a temporary repository that can trigger any of the linters
available, and test against a temporary linter by committing against
the test repository: the linter should be able to access all required
files by using loadData/getData in the LintEngine and Linter.
Revert Plan:
Tags: lint, svn-hook-pre-commit
Reviewers: jungejason, asukhachev, epriestley, aran
Reviewed By: epriestley
CC: aran, jungejason, epriestley, kunalb, asukhachev
Differential Revision: https://secure.phabricator.com/D1256
2011-12-21 05:26:05 +01:00
|
|
|
$this->data[$path] = $this->getEngine()->loadData($path);
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
return $this->data[$path];
|
|
|
|
}
|
|
|
|
|
2011-05-06 17:34:18 +02:00
|
|
|
public function setEngine(ArcanistLintEngine $engine) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$this->engine = $engine;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getEngine() {
|
|
|
|
return $this->engine;
|
|
|
|
}
|
|
|
|
|
2012-11-21 23:52:50 +01:00
|
|
|
public function getCacheVersion() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
public function getLintMessageFullCode($short_code) {
|
|
|
|
return $this->getLinterName().$short_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLintMessageSeverity($code) {
|
|
|
|
$map = $this->customSeverityMap;
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
|
|
|
|
$map = $this->getLintSeverityMap();
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
|
|
|
|
return ArcanistLintSeverity::SEVERITY_ERROR;
|
|
|
|
}
|
|
|
|
|
2011-11-17 06:53:47 +01:00
|
|
|
public function isMessageEnabled($code) {
|
|
|
|
return ($this->getLintMessageSeverity($code) !==
|
|
|
|
ArcanistLintSeverity::SEVERITY_DISABLED);
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
public function getLintMessageName($code) {
|
|
|
|
$map = $this->getLintNameMap();
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
return "Unknown lint message!";
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function addLintMessage(ArcanistLintMessage $message) {
|
2012-02-07 18:57:26 +01:00
|
|
|
if (!$this->getEngine()->getCommitHookMode()) {
|
|
|
|
$root = $this->getEngine()->getWorkingCopy()->getProjectRoot();
|
|
|
|
$path = Filesystem::resolvePath($message->getPath(), $root);
|
|
|
|
$message->setPath(Filesystem::readablePath($path, $root));
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
$this->messages[] = $message;
|
|
|
|
return $message;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLintMessages() {
|
|
|
|
return $this->messages;
|
|
|
|
}
|
|
|
|
|
2013-01-11 00:03:33 +01:00
|
|
|
protected function newLintAtLine($line, $char, $code, $desc) {
|
|
|
|
return id(new ArcanistLintMessage())
|
|
|
|
->setPath($this->getActivePath())
|
|
|
|
->setLine($line)
|
|
|
|
->setChar($char)
|
|
|
|
->setCode($this->getLintMessageFullCode($code))
|
|
|
|
->setSeverity($this->getLintMessageSeverity($code))
|
|
|
|
->setName($this->getLintMessageName($code))
|
|
|
|
->setDescription($desc);
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
protected function raiseLintAtLine(
|
|
|
|
$line,
|
|
|
|
$char,
|
|
|
|
$code,
|
|
|
|
$desc,
|
|
|
|
$original = null,
|
|
|
|
$replacement = null) {
|
|
|
|
|
2013-01-11 00:03:33 +01:00
|
|
|
$message = $this->newLintAtLine($line, $char, $code, $desc)
|
|
|
|
->setOriginalText($original)
|
|
|
|
->setReplacementText($replacement);
|
2011-01-10 00:22:25 +01:00
|
|
|
|
2013-01-11 00:03:33 +01:00
|
|
|
return $this->addLintMessage($message);
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function raiseLintAtPath(
|
|
|
|
$code,
|
|
|
|
$desc) {
|
|
|
|
|
|
|
|
return $this->raiseLintAtLine(null, null, $code, $desc, null, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function raiseLintAtOffset(
|
|
|
|
$offset,
|
|
|
|
$code,
|
|
|
|
$desc,
|
|
|
|
$original = null,
|
|
|
|
$replacement = null) {
|
|
|
|
|
|
|
|
$path = $this->getActivePath();
|
|
|
|
$engine = $this->getEngine();
|
2011-01-10 05:40:13 +01:00
|
|
|
if ($offset === null) {
|
|
|
|
$line = null;
|
|
|
|
$char = null;
|
|
|
|
} else {
|
|
|
|
list($line, $char) = $engine->getLineAndCharFromOffset($path, $offset);
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
|
|
|
|
return $this->raiseLintAtLine(
|
|
|
|
$line + 1,
|
|
|
|
$char + 1,
|
|
|
|
$code,
|
|
|
|
$desc,
|
|
|
|
$original,
|
|
|
|
$replacement);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function willLintPath($path) {
|
|
|
|
$this->stopAllLinters = false;
|
|
|
|
$this->activePath = $path;
|
|
|
|
}
|
|
|
|
|
2012-01-18 01:30:59 +01:00
|
|
|
public function canRun() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
abstract public function willLintPaths(array $paths);
|
|
|
|
abstract public function lintPath($path);
|
|
|
|
abstract public function getLinterName();
|
2012-05-31 21:09:01 +02:00
|
|
|
|
2013-01-11 23:11:38 +01:00
|
|
|
public function didRunLinters() {
|
|
|
|
// This is a hook.
|
|
|
|
}
|
|
|
|
|
2012-05-31 21:09:01 +02:00
|
|
|
public function getLintSeverityMap() {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLintNameMap() {
|
|
|
|
return array();
|
|
|
|
}
|
2011-01-10 00:22:25 +01:00
|
|
|
|
2012-11-22 03:38:24 +01:00
|
|
|
public function getCacheGranularity() {
|
|
|
|
return self::GRANULARITY_FILE;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|