diff --git a/src/lint/linter/ArcanistExternalLinter.php b/src/lint/linter/ArcanistExternalLinter.php --- a/src/lint/linter/ArcanistExternalLinter.php +++ b/src/lint/linter/ArcanistExternalLinter.php @@ -13,6 +13,7 @@ private $bin; private $interpreter; private $flags; + private $minimumVersion; /* -( Interpreters, Binaries and Flags )----------------------------------- */ @@ -140,6 +141,15 @@ return array(); } + /** + * TODO + * + * @return string + */ + protected function getDefaultMinimumVersion() { + return null; + } + /** * Override default flags with custom flags. If not overridden, flags provided @@ -232,6 +242,26 @@ return $this; } + /** + * TODO + * + * @return string + */ + final public function getMinimumVersion() { + return coalesce($this->minimumVersion, $this->getDefaultMinimumVersion()); + } + + /** + * TODO + * + * @param string + * @return this + */ + final public function setMinimumVersion($version) { + $this->minimumVersion = $version; + return $this; + } + /* -( Parsing Linter Output )---------------------------------------------- */ @@ -397,6 +427,14 @@ final protected function buildFutures(array $paths) { $executable = $this->getExecutableCommand(); + $version = $this->getMinimumVersion(); + if ($version) { + if (!$this->compareVersion($version, '>=')) { + // TODO: Provide a more descriptive error message. + throw new ArcanistUsageException('Wrong version'); + } + } + $bin = csprintf('%C %Ls', $executable, $this->getCommandFlags()); $futures = array(); @@ -459,6 +497,10 @@ 'Provide a list of additional flags to pass to the linter on the '. 'command line.'), ), + 'minimum-version' => array( + 'type' => 'optional string', + 'help' => pht(''), + ), ); if ($this->shouldUseInterpreter()) { @@ -528,6 +570,9 @@ } $this->setFlags($value); return; + case 'minimum-version': + $this->minimumVersion = $value; + return; } return parent::setLinterConfigurationValue($key, $value); 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 @@ -312,6 +312,33 @@ return null; } + /** + * Compare the version of the linter with a target version. + * + * @param string The target version for the linter. + * @param string The desired version relationship. The possible values are + * `<`, `<=`, `>`, `>=`, `==`, `=`, `!=` and `<>`. + * @return bool True if the relationship is the one specified by the operator, + * false otherwise. + */ + protected function compareVersion($target_version, $operator) { + $version = $this->getVersion(); + + if ($version === null) { + throw new Exception(pht( + 'Version cannot be compared because %s does not implement the '. + '`getVersion` method', + get_class($this))); + } else if ($version === false) { + // TODO: We should output the minimum version requirement here. + throw new Exception(pht('Unable to parse version.')); + } + + // The PHP version_compare method does a pretty good job in the general + // case. + return version_compare($version, $target_version, $operator); + } + public function didRunLinters() { // This is a hook. }