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.
|
|
|
|
*
|
2014-05-11 22:42:56 +02:00
|
|
|
* @task info Human Readable Information
|
|
|
|
*
|
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();
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
private $customSeverityRules = array();
|
2011-01-10 00:22:25 +01:00
|
|
|
|
2014-05-11 22:42:56 +02:00
|
|
|
|
|
|
|
/* -( Human Readable Information )---------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an optional informative URI where humans can learn more about this
|
|
|
|
* linter.
|
|
|
|
*
|
|
|
|
* For most linters, this should return a link to the project home page. This
|
|
|
|
* is shown on `arc linters`.
|
|
|
|
*
|
|
|
|
* @return string|null Optionally, return an informative URI.
|
|
|
|
* @task info
|
|
|
|
*/
|
|
|
|
public function getInfoURI() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a brief human-readable description of the linter.
|
|
|
|
*
|
|
|
|
* These should be a line or two, and are shown on `arc linters`.
|
|
|
|
*
|
|
|
|
* @return string|null Optionally, return a brief human-readable description.
|
|
|
|
* @task info
|
|
|
|
*/
|
|
|
|
public function getInfoDescription() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a human-readable linter name.
|
|
|
|
*
|
|
|
|
* These are used by `arc linters`, and can let you give a linter a more
|
|
|
|
* presentable name.
|
|
|
|
*
|
|
|
|
* @return string Human-readable linter name.
|
|
|
|
* @task info
|
|
|
|
*/
|
|
|
|
public function getInfoName() {
|
|
|
|
return nonempty(
|
|
|
|
$this->getLinterName(),
|
|
|
|
$this->getLinterConfigurationName(),
|
|
|
|
get_class($this));
|
|
|
|
}
|
|
|
|
|
2014-05-12 05:23:07 +02:00
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
public function getLinterPriority() {
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
public function setCustomSeverityMap(array $map) {
|
|
|
|
$this->customSeverityMap = $map;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
public function setCustomSeverityRules(array $rules) {
|
|
|
|
$this->customSeverityRules = $rules;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getActivePath() {
|
2011-01-10 00:22:25 +01:00
|
|
|
return $this->activePath;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getOtherLocation($offset, $path = null) {
|
2013-02-09 00:04:32 +01:00
|
|
|
if ($path === null) {
|
|
|
|
$path = $this->getActivePath();
|
|
|
|
}
|
|
|
|
|
|
|
|
list($line, $char) = $this->getEngine()->getLineAndCharFromOffset(
|
|
|
|
$path,
|
|
|
|
$offset);
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'path' => $path,
|
|
|
|
'line' => $line + 1,
|
|
|
|
'char' => $char,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function stopAllLinters() {
|
2011-01-10 00:22:25 +01:00
|
|
|
$this->stopAllLinters = true;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function didStopAllLinters() {
|
2011-01-10 00:22:25 +01:00
|
|
|
return $this->stopAllLinters;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function addPath($path) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$this->paths[$path] = $path;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function setPaths(array $paths) {
|
2012-10-20 14:45:22 +02:00
|
|
|
$this->paths = $paths;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
/**
|
|
|
|
* Filter out paths which this linter doesn't act on (for example, because
|
|
|
|
* they are binaries and the linter doesn't apply to binaries).
|
|
|
|
*/
|
2014-05-12 18:48:52 +02:00
|
|
|
final private function filterPaths($paths) {
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
$engine = $this->getEngine();
|
|
|
|
|
|
|
|
$keep = array();
|
|
|
|
foreach ($paths as $path) {
|
|
|
|
if (!$this->shouldLintDeletedFiles() && !$engine->pathExists($path)) {
|
|
|
|
continue;
|
|
|
|
}
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
|
|
|
|
if (!$this->shouldLintDirectories() && $engine->isDirectory($path)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$this->shouldLintBinaryFiles() && $engine->isBinaryFile($path)) {
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
continue;
|
|
|
|
}
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
$keep[] = $path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $keep;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getPaths() {
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
return $this->filterPaths(array_values($this->paths));
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function addData($path, $data) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$this->data[$path] = $data;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function getData($path) {
|
2011-01-10 00:22:25 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function getEngine() {
|
2011-01-10 00:22:25 +01:00
|
|
|
return $this->engine;
|
|
|
|
}
|
|
|
|
|
2012-11-21 23:52:50 +01:00
|
|
|
public function getCacheVersion() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getLintMessageFullCode($short_code) {
|
2011-01-10 00:22:25 +01:00
|
|
|
return $this->getLinterName().$short_code;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getLintMessageSeverity($code) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$map = $this->customSeverityMap;
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
|
|
|
|
$map = $this->getLintSeverityMap();
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
foreach ($this->customSeverityRules as $rule => $severity) {
|
|
|
|
if (preg_match($rule, $code)) {
|
|
|
|
return $severity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-23 20:58:07 +02:00
|
|
|
return $this->getDefaultMessageSeverity($code);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getDefaultMessageSeverity($code) {
|
2011-01-10 00:22:25 +01:00
|
|
|
return ArcanistLintSeverity::SEVERITY_ERROR;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function isMessageEnabled($code) {
|
2011-11-17 06:53:47 +01:00
|
|
|
return ($this->getLintMessageSeverity($code) !==
|
|
|
|
ArcanistLintSeverity::SEVERITY_DISABLED);
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getLintMessageName($code) {
|
2011-01-10 00:22:25 +01:00
|
|
|
$map = $this->getLintNameMap();
|
|
|
|
if (isset($map[$code])) {
|
|
|
|
return $map[$code];
|
|
|
|
}
|
|
|
|
return "Unknown lint message!";
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final 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;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final public function getLintMessages() {
|
2011-01-10 00:22:25 +01:00
|
|
|
return $this->messages;
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function raiseLintAtLine(
|
2011-01-10 00:22:25 +01:00
|
|
|
$line,
|
|
|
|
$char,
|
|
|
|
$code,
|
|
|
|
$desc,
|
|
|
|
$original = null,
|
|
|
|
$replacement = null) {
|
|
|
|
|
2013-02-08 23:30:25 +01:00
|
|
|
$message = id(new ArcanistLintMessage())
|
|
|
|
->setPath($this->getActivePath())
|
|
|
|
->setLine($line)
|
|
|
|
->setChar($char)
|
|
|
|
->setCode($this->getLintMessageFullCode($code))
|
|
|
|
->setSeverity($this->getLintMessageSeverity($code))
|
|
|
|
->setName($this->getLintMessageName($code))
|
|
|
|
->setDescription($desc)
|
2013-01-11 00:03:33 +01:00
|
|
|
->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
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function raiseLintAtPath(
|
2011-01-10 00:22:25 +01:00
|
|
|
$code,
|
|
|
|
$desc) {
|
|
|
|
|
|
|
|
return $this->raiseLintAtLine(null, null, $code, $desc, null, null);
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function raiseLintAtOffset(
|
2011-01-10 00:22:25 +01:00
|
|
|
$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;
|
|
|
|
}
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
public function willLintPaths(array $paths) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
abstract public function lintPath($path);
|
|
|
|
abstract public function getLinterName();
|
2012-05-31 21:09:01 +02:00
|
|
|
|
2014-05-11 22:42:56 +02:00
|
|
|
public function getVersion() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-01-11 23:11:38 +01:00
|
|
|
public function didRunLinters() {
|
|
|
|
// This is a hook.
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:48:52 +02:00
|
|
|
final protected function isCodeEnabled($code) {
|
2013-02-15 00:18:39 +01:00
|
|
|
$severity = $this->getLintMessageSeverity($code);
|
|
|
|
return $this->getEngine()->isSeverityEnabled($severity);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Lay groundwork for configuration-driven linters
Summary:
Ref T2039. That task has a bunch of discussion, but basically we do a poor job of serving the midrange of lint configuration right now.
If you have something simple, the default linters work.
If you have something complex, building your own engine lets you do whatever you want.
But many users want something in between, which isn't really well accommodated. The idea is to let you write a `.arclint` file, which looks something like this:
{
"linters" : {
"css" : {
"type" : "csslint",
"include" : "(\.css$)",
"exclude" : "(^externals/)",
"bin" : "/usr/local/bin/csslint"
},
"js" : {
"type" : "jshint",
"include" : "(\.js$)",
"exclude" : "(^externals/)",
"bin" : "support/bin/jshint",
"interpreter" : "/usr/local/bin/node"
}
}
}
...which will provide a bunch of common options around lint severity, interpreter and binary locaitons, included and excluded files, etc.
This implements some basics, and very rough support in the Filename linter.
Test Plan:
Generated a `.arclint` file and saw it apply filename lint correctly. Used `debug` mode and tried invalid regexps.
{
"debug" : true,
"linters" : {
"filename" : {
"type" : "filename",
"exclude" : ["@^externals/@"]
}
}
}
Next steps include:
- Provide an external linter archetype (T3186) and expose a common set of configuration here ("bin", "interpreter", "flags", "severity").
- Provide a `.arcunit` file which works similarly (it can probably be simpler).
Reviewers: btrahan, Firehed
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2039
Differential Revision: https://secure.phabricator.com/D6797
2013-08-23 01:02:16 +02:00
|
|
|
/**
|
|
|
|
* If this linter is selectable via `.arclint` configuration files, return
|
|
|
|
* a short, human-readable name to identify it. For example, `"jshint"` or
|
|
|
|
* `"pep8"`.
|
|
|
|
*
|
|
|
|
* If you do not implement this method, the linter will not be selectable
|
|
|
|
* through `.arclint` files.
|
|
|
|
*/
|
|
|
|
public function getLinterConfigurationName() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-08-23 20:52:44 +02:00
|
|
|
public function getLinterConfigurationOptions() {
|
2014-05-12 04:28:26 +02:00
|
|
|
if (!$this->canCustomizeLintSeverities()) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
return array(
|
2014-05-12 05:23:07 +02:00
|
|
|
'severity' => array(
|
|
|
|
'type' => 'optional map<string|int, string>',
|
|
|
|
'help' => pht(
|
|
|
|
'Provide a map from lint codes to adjusted severity levels: error, '.
|
|
|
|
'warning, advice, autofix or disabled.')
|
|
|
|
),
|
|
|
|
'severity.rules' => array(
|
|
|
|
'type' => 'optional map<string, string>',
|
|
|
|
'help' => pht(
|
|
|
|
'Provide a map of regular expressions to severity levels. All '.
|
|
|
|
'matching codes have their severity adjusted.'),
|
|
|
|
),
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
);
|
2013-08-23 20:52:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function setLinterConfigurationValue($key, $value) {
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
$sev_map = array(
|
|
|
|
'error' => ArcanistLintSeverity::SEVERITY_ERROR,
|
|
|
|
'warning' => ArcanistLintSeverity::SEVERITY_WARNING,
|
|
|
|
'autofix' => ArcanistLintSeverity::SEVERITY_AUTOFIX,
|
|
|
|
'advice' => ArcanistLintSeverity::SEVERITY_ADVICE,
|
|
|
|
'disabled' => ArcanistLintSeverity::SEVERITY_DISABLED,
|
|
|
|
);
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
switch ($key) {
|
|
|
|
case 'severity':
|
2014-05-12 04:28:26 +02:00
|
|
|
if (!$this->canCustomizeLintSeverities()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
$custom = array();
|
|
|
|
foreach ($value as $code => $severity) {
|
|
|
|
if (empty($sev_map[$severity])) {
|
|
|
|
$valid = implode(', ', array_keys($sev_map));
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Unknown lint severity "%s". Valid severities are: %s.',
|
|
|
|
$severity,
|
|
|
|
$valid));
|
|
|
|
}
|
|
|
|
$code = $this->getLintCodeFromLinterConfigurationKey($code);
|
|
|
|
$custom[$code] = $severity;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setCustomSeverityMap($custom);
|
|
|
|
return;
|
2014-05-12 04:28:26 +02:00
|
|
|
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
case 'severity.rules':
|
2014-05-12 04:28:26 +02:00
|
|
|
if (!$this->canCustomizeLintSeverities()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
foreach ($value as $rule => $severity) {
|
|
|
|
if (@preg_match($rule, '') === false) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Severity rule "%s" is not a valid regular expression.',
|
|
|
|
$rule));
|
|
|
|
}
|
|
|
|
if (empty($sev_map[$severity])) {
|
|
|
|
$valid = implode(', ', array_keys($sev_map));
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Unknown lint severity "%s". Valid severities are: %s.',
|
|
|
|
$severity,
|
|
|
|
$valid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->setCustomSeverityRules($value);
|
|
|
|
return;
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
}
|
|
|
|
|
2013-08-23 20:52:44 +02:00
|
|
|
throw new Exception("Incomplete implementation: {$key}!");
|
|
|
|
}
|
|
|
|
|
2014-05-12 04:28:26 +02:00
|
|
|
protected function canCustomizeLintSeverities() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Ready more linters and linter functions for .arclint
Summary:
Ref T3186. Ref T2039. Continues work on readying linters for `.arclint`.
- **Ruby**: Make this an ExternalLinter.
- **Priority**: Currently, linters have an implicit "correct" order (notably, the "NoLint" linter needs to run before other linters). Make this explicit by introducing `getLinterPriority()`.
- **Binaries**: Currently, linters manually reject binary files. Instead, reject binary files by default (linters can override this if they do want to lint binary files).
- **Deleted Files**: Currently, linters manually reject deleted files (usually in engines). Instead, reject deleted files by default (linters can override this).
- **Severity**: Move this `.arclint` config option up to top level.
- **willLintPaths()**: This method is abstract, but almost all linters provide a trivial implementation. Provide a trivial implementation in the base class.
- **getLintSeverityMap()/getLintNameMap()**: A bunch of linters have empty implementations; these are redundant. Remove them.
- **Spelling**: clean up some dead / test-only / unconventional code.
- **`.arclint`**: Allow the filename, generated, nolint, text, spelling and ruby linters to be configured via `.arclint`.
Test Plan:
https://github.com/epriestley/arclint-examples/commit/458beca3d65b64d52ed612904ae66eb837118b94
Ran unit tests.
Reviewers: btrahan
Reviewed By: btrahan
CC: Firehed, aran
Maniphest Tasks: T2039, T3186
Differential Revision: https://secure.phabricator.com/D6805
2013-08-26 14:37:10 +02:00
|
|
|
protected function shouldLintBinaryFiles() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function shouldLintDeletedFiles() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Support PHPCS as a `.arclint` linter
Summary:
Ref T3186. Ref T2039. Ref T3771. A few effects here:
# Expose PHPCS as a `.arclint` linter.
# Turn PHPCS into an ArcanistExternalLinter linter.
# Add test coverage for PHPCS.
# Add a `severity.rules` option to `.arclint`. Some linters have very explicit builtin severities ("error", "warning") but their meanings are different from how arc interprets these terms. For example, PHPCS raises "wrong indentation level" as an "error". You can already use the "severity" map to adjust individual rules, but if you want to adjust an entire linter it's currently difficult. This rule map makes it easy. There's substantial precedent for this in other linters, notably all the Python linters.
For `severity.rules`, for example, this will turn all PHPCS "errors" into warnings, and all of its warnings into advice:
"severity.rules" : {
"(^PHPCS\\.E\\.)" : "warning",
"(^PHPCS\\.W\\.)" : "advice"
}
The user can use `severity` (or more rules) to get additional granularity adjustments if they desire.
Test Plan: https://github.com/epriestley/arclint-examples/commit/5bb919bc3a684d6654dcc28622de9a29ec08307d
Reviewers: btrahan
Reviewed By: btrahan
CC: aran, ajtrichards
Maniphest Tasks: T2039, T3186, T3771
Differential Revision: https://secure.phabricator.com/D6830
2013-08-29 15:47:27 +02:00
|
|
|
protected function shouldLintDirectories() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Map a configuration lint code to an `arc` lint code. Primarily, this is
|
|
|
|
* intended for validation, but can also be used to normalize case or
|
|
|
|
* otherwise be more permissive in accepted inputs.
|
|
|
|
*
|
|
|
|
* If the code is not recognized, you should throw an exception.
|
|
|
|
*
|
|
|
|
* @param string Code specified in configuration.
|
|
|
|
* @return string Normalized code to use in severity map.
|
|
|
|
*/
|
|
|
|
protected function getLintCodeFromLinterConfigurationKey($code) {
|
|
|
|
return $code;
|
|
|
|
}
|
|
|
|
|
2014-05-12 03:39:28 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve an old lint configuration value from `.arcconfig` or a similar
|
|
|
|
* source.
|
|
|
|
*
|
|
|
|
* Modern linters should use @{method:getConfig} to read configuration from
|
|
|
|
* `.arclint`.
|
|
|
|
*
|
|
|
|
* @param string Configuration key to retrieve.
|
|
|
|
* @param wild Default value to return if key is not present in config.
|
|
|
|
* @return wild Configured value, or default if no configuration exists.
|
|
|
|
*/
|
|
|
|
protected function getDeprecatedConfiguration($key, $default = null) {
|
|
|
|
|
|
|
|
// If we're being called in a context without an engine (probably from
|
|
|
|
// `arc linters`), just return the default value.
|
|
|
|
if (!$this->engine) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
|
|
|
$config = $this->getEngine()->getConfigurationManager();
|
|
|
|
|
|
|
|
// Construct a sentinel object so we can tell if we're reading config
|
|
|
|
// or not.
|
|
|
|
$sentinel = (object)array();
|
|
|
|
$result = $config->getConfigFromAnySource($key, $sentinel);
|
|
|
|
|
|
|
|
// If we read config, warn the user that this mechanism is deprecated and
|
|
|
|
// discouraged.
|
|
|
|
if ($result !== $sentinel) {
|
|
|
|
$console = PhutilConsole::getConsole();
|
|
|
|
$console->writeErr(
|
|
|
|
"**%s**: %s\n",
|
|
|
|
pht('Deprecation Warning'),
|
|
|
|
pht(
|
|
|
|
'Configuration option "%s" is deprecated. Generally, linters should '.
|
|
|
|
'now be configured using an `.arclint` file. See "Arcanist User '.
|
|
|
|
'Guide: Lint" in the documentation for more information.',
|
|
|
|
$key));
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
2011-01-10 00:22:25 +01:00
|
|
|
}
|