Changeset View
Changeset View
Standalone View
Standalone View
src/lint/operation/ArcanistLintEngine.php
- This file was moved from src/lint/engine/ArcanistLintEngine.php.
<?php | <?php | ||||
/** | abstract class ArcanistLintEngine | ||||
* Manages lint execution. When you run 'arc lint' or 'arc diff', Arcanist | extends ArcanistOperationEngine { | ||||
* attempts to run lint rules using a lint engine. | |||||
* | |||||
* Lint engines are high-level strategic classes which do not contain any | |||||
* actual linting rules. Linting rules live in `Linter` classes. The lint | |||||
* engine builds and configures linters. | |||||
* | |||||
* Most modern linters can be configured with an `.arclint` file, which is | |||||
* managed by the builtin @{class:ArcanistConfigurationDrivenLintEngine}. | |||||
* Consult the documentation for more information on these files. | |||||
* | |||||
* In the majority of cases, you do not need to write a custom lint engine. | |||||
* For example, to add new rules for a new language, write a linter instead. | |||||
* However, if you have a very advanced or specialized use case, you can write | |||||
* a custom lint engine by extending this class; custom lint engines are more | |||||
* powerful but much more complex than the builtin engines. | |||||
* | |||||
* The lint engine is given a list of paths (generally, the paths that you | |||||
* modified in your change) and determines which linters to run on them. The | |||||
* linters themselves are responsible for actually analyzing file text and | |||||
* finding warnings and errors. For example, if the modified paths include some | |||||
* JS files and some Python files, you might want to run JSLint on the JS files | |||||
* and PyLint on the Python files. | |||||
* | |||||
* You can also run multiple linters on a single file. For instance, you might | |||||
* run one linter on all text files to make sure they don't have trailing | |||||
* whitespace, or enforce tab vs space rules, or make sure there are enough | |||||
* curse words in them. | |||||
* | |||||
* You can test an engine like this: | |||||
* | |||||
* arc lint --engine YourLintEngineClassName --lintall some_file.py | |||||
* | |||||
* ...which will show you all the lint issues raised in the file. | |||||
* | |||||
* See @{article@phabricator:Arcanist User Guide: Customizing Lint, Unit Tests | |||||
* and Workflows} for more information about configuring lint engines. | |||||
*/ | |||||
epriestley: I'm saving the stuff I'm deleting in a file, but I'd generally like to get more documentation… | |||||
abstract class ArcanistLintEngine extends Phobject { | |||||
protected $workingCopy; | protected $workingCopy; | ||||
protected $paths = array(); | protected $paths = array(); | ||||
protected $fileData = array(); | protected $fileData = array(); | ||||
protected $charToLine = array(); | |||||
protected $lineToFirstChar = array(); | |||||
private $cachedResults; | private $cachedResults; | ||||
private $cacheVersion; | private $cacheVersion; | ||||
private $repositoryVersion; | private $repositoryVersion; | ||||
private $results = array(); | private $results = array(); | ||||
private $stopped = array(); | private $stopped = array(); | ||||
private $minimumSeverity = ArcanistLintSeverity::SEVERITY_DISABLED; | private $minimumSeverity = ArcanistLintSeverity::SEVERITY_DISABLED; | ||||
private $changedLines = array(); | private $changedLines = array(); | ||||
private $configurationManager; | private $configurationManager; | ||||
private $linterResources = array(); | private $linterResources = array(); | ||||
public function __construct() {} | |||||
final public function setConfigurationManager( | |||||
ArcanistConfigurationManager $configuration_manager) { | |||||
$this->configurationManager = $configuration_manager; | |||||
return $this; | |||||
} | |||||
final public function getConfigurationManager() { | |||||
return $this->configurationManager; | |||||
} | |||||
final public function setWorkingCopy( | |||||
ArcanistWorkingCopyIdentity $working_copy) { | |||||
$this->workingCopy = $working_copy; | |||||
return $this; | |||||
} | |||||
final public function getWorkingCopy() { | |||||
return $this->workingCopy; | |||||
} | |||||
final public function setPaths($paths) { | final public function getUnitEngineType() { | ||||
$this->paths = $paths; | return $this->getPhobjectClassConstant('ENGINETYPE'); | ||||
return $this; | |||||
} | } | ||||
public function getPaths() { | public static function getAllLintEngines() { | ||||
return $this->paths; | return id(new PhutilClassMapQuery()) | ||||
->setAncestorClass(__CLASS__) | |||||
->setUniqueMethod('getLintEngineType') | |||||
->execute(); | |||||
} | } | ||||
final public function setPathChangedLines($path, $changed) { | final public function setPathChangedLines($path, $changed) { | ||||
if ($changed === null) { | if ($changed === null) { | ||||
$this->changedLines[$path] = null; | $this->changedLines[$path] = null; | ||||
} else { | } else { | ||||
$this->changedLines[$path] = array_fill_keys($changed, true); | $this->changedLines[$path] = array_fill_keys($changed, true); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | if (empty($this->results[$path])) { | ||||
$result = new ArcanistLintResult(); | $result = new ArcanistLintResult(); | ||||
$result->setPath($path); | $result->setPath($path); | ||||
$result->setCacheVersion($this->cacheVersion); | $result->setCacheVersion($this->cacheVersion); | ||||
$this->results[$path] = $result; | $this->results[$path] = $result; | ||||
} | } | ||||
return $this->results[$path]; | return $this->results[$path]; | ||||
} | } | ||||
final public function getLineAndCharFromOffset($path, $offset) { | |||||
epriestleyAuthorUnsubmitted Done Inline ActionsThis moved to ArcanistWorkingCopyPath. epriestley: This moved to `ArcanistWorkingCopyPath`. | |||||
if (!isset($this->charToLine[$path])) { | |||||
$char_to_line = array(); | |||||
$line_to_first_char = array(); | |||||
$lines = explode("\n", $this->loadData($path)); | |||||
$line_number = 0; | |||||
$line_start = 0; | |||||
foreach ($lines as $line) { | |||||
$len = strlen($line) + 1; // Account for "\n". | |||||
$line_to_first_char[] = $line_start; | |||||
$line_start += $len; | |||||
for ($ii = 0; $ii < $len; $ii++) { | |||||
$char_to_line[] = $line_number; | |||||
} | |||||
$line_number++; | |||||
} | |||||
$this->charToLine[$path] = $char_to_line; | |||||
$this->lineToFirstChar[$path] = $line_to_first_char; | |||||
} | |||||
$line = $this->charToLine[$path][$offset]; | |||||
$char = $offset - $this->lineToFirstChar[$path][$line]; | |||||
return array($line, $char); | |||||
} | |||||
protected function getCacheVersion() { | protected function getCacheVersion() { | ||||
return 1; | return 1; | ||||
} | } | ||||
/** | /** | ||||
* Get a named linter resource shared by another linter. | * Get a named linter resource shared by another linter. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 203 Lines • Show Last 20 Lines |
I'm saving the stuff I'm deleting in a file, but I'd generally like to get more documentation like this into the actual documentation and not in the source code later on.
The actual documentation is now wrong, e.g. I've removed --engine.