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 @@ -14,6 +14,7 @@ private $interpreter; private $flags; private $versionRequirement; + private $interpreterFlags; /* -( Interpreters, Binaries and Flags )----------------------------------- */ @@ -197,6 +198,52 @@ 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 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 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 )---------------------------------------------- */ @@ -351,14 +398,20 @@ $this->checkBinaryConfiguration(); $interpreter = null; + $interpreter_flags = array(); if ($this->shouldUseInterpreter()) { $interpreter = $this->getInterpreter(); + $interpreter_flags = $this->getInterpreterFlags(); } $binary = $this->getBinary(); if ($interpreter) { - $bin = csprintf('%s %s', $interpreter, $binary); + if (!empty($interpreter_flags)) { + $bin = csprintf('%s %Ls %s', $interpreter, $interpreter_flags, $binary); + } else { + $bin = csprintf('%s %s', $interpreter, $binary); + } } else { $bin = csprintf('%s', $binary); } @@ -379,6 +432,23 @@ nonempty($this->flags, $this->getDefaultFlags())); } + /** + * Get the composed flags for the interpreter, including both mandatory and + * configured flags. + * + * @return list 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() { try { $this->checkBinaryConfiguration(); @@ -495,6 +565,13 @@ 'a list of possible interpreters, the first one that exists '. 'will be used.'), ); + + $options['interpreter.flags'] = array( + 'type' => 'optional list', + 'help' => pht( + 'Provide a list of additional flags to pass to the interpreter on '. + 'the command line.'), + ); } return $options + parent::getLinterConfigurationOptions(); @@ -545,6 +622,9 @@ case 'flags': $this->setFlags($value); return; + case 'interpreter.flags': + $this->setInterpreterFlags($value); + return; case 'version': $this->setVersionRequirement($value); return;