Changeset View
Changeset View
Standalone View
Standalone View
src/lint/linter/ArcanistExternalLinter.php
| <?php | <?php | ||||
| /** | /** | ||||
| * Base class for linters which operate by invoking an external program and | * Base class for linters which operate by invoking an external program and | ||||
| * parsing results. | * parsing results. | ||||
| * | * | ||||
| * @task bin Interpreters, Binaries and Flags | * @task bin Interpreters, Binaries and Flags | ||||
| * @task parse Parsing Linter Output | * @task parse Parsing Linter Output | ||||
| * @task exec Executing the Linter | * @task exec Executing the Linter | ||||
| */ | */ | ||||
| abstract class ArcanistExternalLinter extends ArcanistFutureLinter { | abstract class ArcanistExternalLinter extends ArcanistFutureLinter { | ||||
| private $bin; | private $bin; | ||||
| private $interpreter; | private $interpreter; | ||||
| private $flags; | private $flags; | ||||
| private $versionRequirement; | private $versionRequirement; | ||||
| private $interpreterFlags; | |||||
| /* -( Interpreters, Binaries and Flags )----------------------------------- */ | /* -( Interpreters, Binaries and Flags )----------------------------------- */ | ||||
| /** | /** | ||||
| * Return the default binary name or binary path where the external linter | * Return the default binary name or binary path where the external linter | ||||
| * lives. This can either be a binary name which is expected to be installed | * lives. This can either be a binary name which is expected to be installed | ||||
| * in PATH (like "jshint"), or a relative path from the project root | * in PATH (like "jshint"), or a relative path from the project root | ||||
| ▲ Show 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | /* -( Interpreters, Binaries and Flags )----------------------------------- */ | ||||
| * @return this | * @return this | ||||
| * @task bin | * @task bin | ||||
| */ | */ | ||||
| final public function setInterpreter($interpreter) { | final public function setInterpreter($interpreter) { | ||||
| $this->interpreter = $interpreter; | $this->interpreter = $interpreter; | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| /** | |||||
| * Return array of flags needed by the interpreter, such as "-jar" when | |||||
| * using java as the interpreter. This method is only invoked if | |||||
| * @{method:shouldUseInterpreter} has been overridden to return 'true'. | |||||
| * | |||||
| * @return array Flags to pass to interpreter | |||||
| * @task bin | |||||
| */ | |||||
| protected function getDefaultInterpreterFlags() { | |||||
| return array(); | |||||
| } | |||||
| /** | |||||
| * Provide mandatory, non-overridable flags to the linter interpreter. | |||||
| * Generally these are arguments to configure invocation of the interpreter | |||||
| * such as (assuming Java interpreter) `-Xmx1024m`, `-Dproperty=value`, or | |||||
| * in the case of the binary being a jar file, the last one should be `-jar`. | |||||
| * | |||||
| * Due to the specific case of using java as interpreter and a jarfile as | |||||
| * the binary, the `-jar` argument must appear last in the list of all | |||||
| * flags passed to interpreter. For this, manadatory flags are ensured to | |||||
| * always be listed before any default or user overridden flags. | |||||
| * | |||||
| * Flags which are not mandatory should be provided in | |||||
| * @{method:getDefaultInterpreterFlags} instead. | |||||
| * | |||||
| * @return list<string> Mandatory flags, like `"-jar"`. | |||||
| * @task bin | |||||
| */ | |||||
| protected function getMandatoryInterpreterFlags() { | |||||
| return array(); | |||||
| } | |||||
| /** | |||||
| * Override default interpreter flags with custom flags. If not overridden, | |||||
| * flags provided by @{method:getDefaultInterpreterFlags} are used. | |||||
| * | |||||
| * @param list<string> New flags for the interpreter. | |||||
| * @return this | |||||
| * @task bin | |||||
| */ | |||||
| final public function setInterpreterFlags(array $interpreter_flags) { | |||||
| $this->interpreterFlags = $interpreter_flags; | |||||
| return $this; | |||||
| } | |||||
| /* -( Parsing Linter Output )---------------------------------------------- */ | /* -( Parsing Linter Output )---------------------------------------------- */ | ||||
| /** | /** | ||||
| * Parse the output of the external lint program into objects of class | * Parse the output of the external lint program into objects of class | ||||
| * @{class:ArcanistLintMessage} which `arc` can consume. Generally, this | * @{class:ArcanistLintMessage} which `arc` can consume. Generally, this | ||||
| * means examining the output and converting each warning or error into a | * means examining the output and converting each warning or error into a | ||||
| * message. | * message. | ||||
| ▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | /* -( Executing the Linter )----------------------------------------------- */ | ||||
| * | * | ||||
| * @return string Command to execute the raw linter. | * @return string Command to execute the raw linter. | ||||
| * @task exec | * @task exec | ||||
| */ | */ | ||||
| final protected function getExecutableCommand() { | final protected function getExecutableCommand() { | ||||
| $this->checkBinaryConfiguration(); | $this->checkBinaryConfiguration(); | ||||
| $interpreter = null; | $interpreter = null; | ||||
| $interpreter_flags = array(); | |||||
| if ($this->shouldUseInterpreter()) { | if ($this->shouldUseInterpreter()) { | ||||
| $interpreter = $this->getInterpreter(); | $interpreter = $this->getInterpreter(); | ||||
| $interpreter_flags = $this->getInterpreterFlags(); | |||||
| } | } | ||||
| $binary = $this->getBinary(); | $binary = $this->getBinary(); | ||||
| if ($interpreter) { | if ($interpreter) { | ||||
| if (!empty($interpreter_flags)) { | |||||
| $bin = csprintf('%s %Ls %s', $interpreter, $interpreter_flags, $binary); | |||||
| } else { | |||||
| $bin = csprintf('%s %s', $interpreter, $binary); | $bin = csprintf('%s %s', $interpreter, $binary); | ||||
| } | |||||
| } else { | } else { | ||||
| $bin = csprintf('%s', $binary); | $bin = csprintf('%s', $binary); | ||||
| } | } | ||||
| return $bin; | return $bin; | ||||
| } | } | ||||
| /** | /** | ||||
| * Get the composed flags for the executable, including both mandatory and | * Get the composed flags for the executable, including both mandatory and | ||||
| * configured flags. | * configured flags. | ||||
| * | * | ||||
| * @return list<string> Composed flags. | * @return list<string> Composed flags. | ||||
| * @task exec | * @task exec | ||||
| */ | */ | ||||
| final protected function getCommandFlags() { | final protected function getCommandFlags() { | ||||
| return array_merge( | return array_merge( | ||||
| $this->getMandatoryFlags(), | $this->getMandatoryFlags(), | ||||
| nonempty($this->flags, $this->getDefaultFlags())); | nonempty($this->flags, $this->getDefaultFlags())); | ||||
| } | } | ||||
| /** | |||||
| * Get the composed flags for the interpreter, including both mandatory and | |||||
| * configured flags. | |||||
| * | |||||
| * @return list<string> Composed interpreter flags. | |||||
| * @task exec | |||||
| */ | |||||
| final protected function getInterpreterFlags() { | |||||
| // Note that this forces the mandatory flags to appear before any other | |||||
| // flags provided through default or overridden. This is to handle the | |||||
| // the case of java interpreter needing to combine the `-jar` flag followed | |||||
| // immediately by the binary which would be the jar file. | |||||
| return array_merge( | |||||
| nonempty($this->interpreterFlags, $this->getDefaultInterpreterFlags()), | |||||
| $this->getMandatoryInterpreterFlags()); | |||||
| } | |||||
| public function getCacheVersion() { | public function getCacheVersion() { | ||||
| try { | try { | ||||
| $this->checkBinaryConfiguration(); | $this->checkBinaryConfiguration(); | ||||
| } catch (ArcanistMissingLinterException $e) { | } catch (ArcanistMissingLinterException $e) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| $version = $this->getVersion(); | $version = $this->getVersion(); | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | if ($this->shouldUseInterpreter()) { | ||||
| $options['interpreter'] = array( | $options['interpreter'] = array( | ||||
| 'type' => 'optional string | list<string>', | 'type' => 'optional string | list<string>', | ||||
| 'help' => pht( | 'help' => pht( | ||||
| 'Specify a string (or list of strings) identifying the interpreter '. | 'Specify a string (or list of strings) identifying the interpreter '. | ||||
| 'which should be used to invoke the linter binary. If you provide '. | 'which should be used to invoke the linter binary. If you provide '. | ||||
| 'a list of possible interpreters, the first one that exists '. | 'a list of possible interpreters, the first one that exists '. | ||||
| 'will be used.'), | 'will be used.'), | ||||
| ); | ); | ||||
| $options['interpreter.flags'] = array( | |||||
| 'type' => 'optional list<string>', | |||||
| 'help' => pht( | |||||
| 'Provide a list of additional flags to pass to the interpreter on '. | |||||
| 'the command line.'), | |||||
| ); | |||||
| } | } | ||||
| return $options + parent::getLinterConfigurationOptions(); | return $options + parent::getLinterConfigurationOptions(); | ||||
| } | } | ||||
| public function setLinterConfigurationValue($key, $value) { | public function setLinterConfigurationValue($key, $value) { | ||||
| switch ($key) { | switch ($key) { | ||||
| case 'interpreter': | case 'interpreter': | ||||
| Show All 34 Lines | switch ($key) { | ||||
| } | } | ||||
| } | } | ||||
| throw new Exception( | throw new Exception( | ||||
| pht('None of the configured binaries can be located.')); | pht('None of the configured binaries can be located.')); | ||||
| case 'flags': | case 'flags': | ||||
| $this->setFlags($value); | $this->setFlags($value); | ||||
| return; | return; | ||||
| case 'interpreter.flags': | |||||
| $this->setInterpreterFlags($value); | |||||
| return; | |||||
| case 'version': | case 'version': | ||||
| $this->setVersionRequirement($value); | $this->setVersionRequirement($value); | ||||
| return; | return; | ||||
| } | } | ||||
| return parent::setLinterConfigurationValue($key, $value); | return parent::setLinterConfigurationValue($key, $value); | ||||
| } | } | ||||
| Show All 15 Lines | |||||