Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15417540
D13942.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D13942.diff
View Options
diff --git a/.arclint b/.arclint
--- a/.arclint
+++ b/.arclint
@@ -45,15 +45,7 @@
"xhpast": {
"type": "xhpast",
"include": "(\\.php$)",
- "severity": {
- "16": "advice",
- "34": "error"
- },
- "xhpast.blacklisted.function": {
- "eval": "The eval() function should be avoided. It is potentially unsafe and makes debugging more difficult."
- },
- "xhpast.php-version": "5.2.3",
- "xhpast.php-version.windows": "5.3.0"
+ "standard": "phutil.xhpast"
}
}
}
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -161,6 +161,8 @@
'ArcanistLintSeverity' => 'lint/ArcanistLintSeverity.php',
'ArcanistLintWorkflow' => 'workflow/ArcanistLintWorkflow.php',
'ArcanistLinter' => 'lint/linter/ArcanistLinter.php',
+ 'ArcanistLinterStandard' => 'lint/linter/standards/ArcanistLinterStandard.php',
+ 'ArcanistLinterStandardTestCase' => 'lint/linter/standards/__tests__/ArcanistLinterStandardTestCase.php',
'ArcanistLinterTestCase' => 'lint/linter/__tests__/ArcanistLinterTestCase.php',
'ArcanistLintersWorkflow' => 'workflow/ArcanistLintersWorkflow.php',
'ArcanistListAssignmentXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistListAssignmentXHPASTLinterRule.php',
@@ -202,6 +204,7 @@
'ArcanistPhrequentWorkflow' => 'workflow/ArcanistPhrequentWorkflow.php',
'ArcanistPhutilLibraryLinter' => 'lint/linter/ArcanistPhutilLibraryLinter.php',
'ArcanistPhutilXHPASTLinter' => 'lint/linter/ArcanistPhutilXHPASTLinter.php',
+ 'ArcanistPhutilXHPASTLinterStandard' => 'lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php',
'ArcanistPhutilXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistPhutilXHPASTLinterTestCase.php',
'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php',
'ArcanistPregQuoteMisuseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php',
@@ -450,6 +453,8 @@
'ArcanistLintSeverity' => 'Phobject',
'ArcanistLintWorkflow' => 'ArcanistWorkflow',
'ArcanistLinter' => 'Phobject',
+ 'ArcanistLinterStandard' => 'Phobject',
+ 'ArcanistLinterStandardTestCase' => 'PhutilTestCase',
'ArcanistLinterTestCase' => 'PhutilTestCase',
'ArcanistLintersWorkflow' => 'ArcanistWorkflow',
'ArcanistListAssignmentXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@@ -491,6 +496,7 @@
'ArcanistPhrequentWorkflow' => 'ArcanistWorkflow',
'ArcanistPhutilLibraryLinter' => 'ArcanistLinter',
'ArcanistPhutilXHPASTLinter' => 'ArcanistBaseXHPASTLinter',
+ 'ArcanistPhutilXHPASTLinterStandard' => 'ArcanistLinterStandard',
'ArcanistPhutilXHPASTLinterTestCase' => 'ArcanistLinterTestCase',
'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistPregQuoteMisuseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
diff --git a/src/lint/linter/ArcanistLinter.php b/src/lint/linter/ArcanistLinter.php
--- a/src/lint/linter/ArcanistLinter.php
+++ b/src/lint/linter/ArcanistLinter.php
@@ -196,7 +196,6 @@
return;
}
-
public function getLinterPriority() {
return 1.0;
}
@@ -209,6 +208,11 @@
return $this;
}
+ public function addCustomSeverityMap(array $map) {
+ $this->customSeverityMap = $this->customSeverityMap + $map;
+ return $this;
+ }
+
final public function setCustomSeverityRules(array $rules) {
$this->customSeverityRules = $rules;
return $this;
@@ -490,6 +494,10 @@
'Provide a map of regular expressions to severity levels. All '.
'matching codes have their severity adjusted.'),
),
+ 'standard' => array(
+ 'type' => 'optional string | list<string>',
+ 'help' => pht('The coding standard(s) to apply.'),
+ ),
);
}
@@ -548,6 +556,22 @@
}
$this->setCustomSeverityRules($value);
return;
+
+ case 'standard':
+ $standards = (array)$value;
+
+ foreach ($standards as $standard) {
+ $standard = ArcanistLinterStandard::getStandard($value, $this);
+
+ foreach ($standard->getLinterConfiguration() as $k => $v) {
+ $this->setLinterConfigurationValue($k, $v);
+ }
+ $this->addCustomSeverityMap($standard->getLinterSeverityMap());
+ }
+
+ return;
+
+
}
throw new Exception(pht('Incomplete implementation: %s!', $key));
diff --git a/src/lint/linter/standards/ArcanistLinterStandard.php b/src/lint/linter/standards/ArcanistLinterStandard.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/standards/ArcanistLinterStandard.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * A "linter standard" is a collection of linter rules with associated
+ * severities and configuration.
+ *
+ * Basically, a linter standard allows a set of linter rules and configuration
+ * to be easily reused across multiple repositories without duplicating the
+ * contents of the `.arclint` file (and the associated maintenance costs in
+ * keeping changes to this file synchronized).
+ */
+abstract class ArcanistLinterStandard extends Phobject {
+
+ /**
+ * Returns a unique identifier for the linter standard.
+ *
+ * @return string
+ */
+ abstract public function getKey();
+
+ /**
+ * Returns a human-readable name for the linter standard.
+ *
+ * @return string
+ */
+ abstract public function getName();
+
+ /**
+ * Returns a human-readable description for the linter standard.
+ *
+ * @return string
+ */
+ abstract public function getDescription();
+
+ /**
+ * Checks whether the linter standard supports a specified linter.
+ *
+ * @param ArcanistLinter The linter which is being configured.
+ * @return bool True if the linter standard supports the specified
+ * linter, otherwise false.
+ */
+ abstract public function supportsLinter(ArcanistLinter $linter);
+
+ /**
+ * Get linter configuration.
+ *
+ * Returns linter configuration which is passed to
+ * @{method:ArcanistLinter::setLinterConfigurationValue}.
+ *
+ * @return map<string, wild>
+ */
+ public function getLinterConfiguration() {
+ return array();
+ }
+
+ /**
+ * Get linter severities.
+ *
+ * Returns linter severities which are passed to
+ * @{method:ArcanistLinter::addCustomSeverityMap}.
+ *
+ * @return map
+ */
+ public function getLinterSeverityMap() {
+ return array();
+ }
+
+ /**
+ * Load a linter standard by key.
+ *
+ * @param string
+ * @param ArcanistLinter
+ * @return ArcanistLinterStandard
+ */
+ final public static function getStandard($key, ArcanistLinter $linter) {
+ $standards = self::loadAllStandardsForLinter($linter);
+
+ if (empty($standards[$key])) {
+ throw new ArcanistUsageException(
+ pht(
+ 'No such linter standard. Available standards are: %s.',
+ implode(', ', array_keys($standards))));
+ }
+
+ return $standards[$key];
+ }
+
+ /**
+ * Load all linter standards.
+ *
+ * @return list<ArcanistLinterStandard>
+ */
+ final public static function loadAllStandards() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getKey')
+ ->execute();
+ }
+
+ /**
+ * Load all linter standards which support a specified linter.
+ *
+ * @param ArcanistLinter
+ * @return list<ArcanistLinterStandard>
+ */
+ final public static function loadAllStandardsForLinter(
+ ArcanistLinter $linter) {
+
+ $all_standards = self::loadAllStandards();
+ $standards = array();
+
+ foreach ($all_standards as $standard) {
+ if ($standard->supportsLinter($linter)) {
+ $standards[$standard->getKey()] = $standard;
+ }
+ }
+
+ return $standards;
+ }
+
+}
diff --git a/src/lint/linter/standards/__tests__/ArcanistLinterStandardTestCase.php b/src/lint/linter/standards/__tests__/ArcanistLinterStandardTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/standards/__tests__/ArcanistLinterStandardTestCase.php
@@ -0,0 +1,10 @@
+<?php
+
+final class ArcanistLinterStandardTestCase extends PhutilTestCase {
+
+ public function testLoadAllStandards() {
+ ArcanistLinterStandard::loadAllStandards();
+ $this->assertTrue(true);
+ }
+
+}
diff --git a/src/lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php b/src/lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php
@@ -0,0 +1,45 @@
+<?php
+
+final class ArcanistPhutilXHPASTLinterStandard
+ extends ArcanistLinterStandard {
+
+ public function getKey() {
+ return 'phutil.xhpast';
+ }
+
+ public function getName() {
+ return pht('Phutil XHPAST');
+ }
+
+ public function getDescription() {
+ return pht('PHP Coding Standards for Phutil libraries.');
+ }
+
+ public function supportsLinter(ArcanistLinter $linter) {
+ return $linter instanceof ArcanistXHPASTLinter;
+ }
+
+ public function getLinterConfiguration() {
+ return array(
+ 'xhpast.blacklisted.function' => array(
+ 'eval' => pht(
+ 'The `%s` function should be avoided. It is potentially unsafe '.
+ 'and makes debugging more difficult.',
+ 'eval'),
+ 'xhpast.php-version' => '5.2.3',
+ 'xhpast.php-version.windows' => '5.3.0',
+ ),
+ );
+ }
+
+ public function getLinterSeverityMap() {
+ $advice = ArcanistLintSeverity::SEVERITY_ADVICE;
+ $error = ArcanistLintSeverity::SEVERITY_ERROR;
+
+ return array(
+ ArcanistTodoCommentXHPASTLinterRule::ID => $advice,
+ ArcanistCommentSpacingXHPASTLinterRule::ID => $error,
+ );
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 21, 5:28 PM (3 d, 3 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7222225
Default Alt Text
D13942.diff (9 KB)
Attached To
Mode
D13942: Add XHAST linter standards
Attached
Detach File
Event Timeline
Log In to Comment