diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 22800f0f..53f297db 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -104,6 +104,7 @@ phutil_register_library_map(array( 'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php', 'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php', 'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php', + 'ArcanistScalaSBTLinter' => 'lint/linter/ArcanistScalaSBTLinter.php', 'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php', 'ArcanistSetConfigWorkflow' => 'workflow/ArcanistSetConfigWorkflow.php', 'ArcanistSettings' => 'configuration/ArcanistSettings.php', @@ -215,6 +216,7 @@ phutil_register_library_map(array( 'ArcanistPyLintLinter' => 'ArcanistLinter', 'ArcanistRubyLinter' => 'ArcanistLinter', 'ArcanistRubyLinterTestCase' => 'ArcanistArcanistLinterTestCase', + 'ArcanistScalaSBTLinter' => 'ArcanistLinter', 'ArcanistScriptAndRegexLinter' => 'ArcanistLinter', 'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow', diff --git a/src/lint/engine/ComprehensiveLintEngine.php b/src/lint/engine/ComprehensiveLintEngine.php index 432d4c00..9adae4ec 100644 --- a/src/lint/engine/ComprehensiveLintEngine.php +++ b/src/lint/engine/ComprehensiveLintEngine.php @@ -45,6 +45,9 @@ final class ComprehensiveLintEngine extends ArcanistLintEngine { $linters[] = id(new ArcanistRubyLinter()) ->setPaths(preg_grep('/\.rb$/', $paths)); + $linters[] = id(new ArcanistScalaSBTLinter()) + ->setPaths(preg_grep('/\.scala$/', $paths)); + $linters[] = id(new ArcanistJSHintLinter()) ->setPaths(preg_grep('/\.js$/', $paths)); diff --git a/src/lint/linter/ArcanistScalaSBTLinter.php b/src/lint/linter/ArcanistScalaSBTLinter.php new file mode 100644 index 00000000..cccc8b22 --- /dev/null +++ b/src/lint/linter/ArcanistScalaSBTLinter.php @@ -0,0 +1,106 @@ +getEngine()->getWorkingCopy(); + $prefix = $working_copy->getConfig('lint.scala_sbt.prefix'); + if ($prefix !== null) { + $sbt_bin = $prefix . $sbt_bin; + } + + if (!Filesystem::pathExists($sbt_bin)) { + + list($err) = exec_manual('which %s', $sbt_bin); + if ($err) { + throw new ArcanistUsageException( + "SBT does not appear to be installed on this system. Install it or ". + "add 'lint.scala_sbt.prefix' in your .arcconfig to point to ". + "the directory where it resides."); + } + } + + return $sbt_bin; + } + + private function getMessageCodeSeverity($type_of_error) { + switch ($type_of_error) { + case 'warn': + return ArcanistLintSeverity::SEVERITY_WARNING; + case 'error': + return ArcanistLintSeverity::SEVERITY_ERROR; + } + } + + public function lintPath($path) { + $sbt = $this->getSBTPath(); + + // Tell SBT to not use color codes so our regex life is easy. + // TODO: Should this be "clean compile" instead of "compile"? + $f = new ExecFuture("%s -Dsbt.log.noformat=true compile", $sbt); + list($err, $stdout, $stderr) = $f->resolve(); + + $lines = explode("\n", $stdout); + $messages = array(); + foreach ($lines as $line) { + $matches = null; + if (!preg_match( + "/\[(warn|error)\] (.*?):(\d+): (.*?)$/", + $line, + $matches)) { + continue; + } + foreach ($matches as $key => $match) { + $matches[$key] = trim($match); + } + + $message = new ArcanistLintMessage(); + $message->setPath($matches[2]); + $message->setLine($matches[3]); + $message->setCode($this->getLinterName()); + $message->setDescription($matches[4]); + $message->setSeverity($this->getMessageCodeSeverity($matches[1])); + $this->addLintMessage($message); + } + } + +}