mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-01 19:22:41 +01:00
Add a very basic Scala (SBT) linter.
Summary: SBT is the most common Scala buildsystem. This adds an extremely basic and slightly horrible linter to check SBT's output for warnings and errors. Test Plan: Tested this with a Scala project I've been working on for some time. It seemed relatively sane. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D4064
This commit is contained in:
parent
6cb8d483b2
commit
b549f565c9
3 changed files with 111 additions and 0 deletions
|
@ -104,6 +104,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
|
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
|
||||||
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
|
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
|
||||||
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php',
|
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php',
|
||||||
|
'ArcanistScalaSBTLinter' => 'lint/linter/ArcanistScalaSBTLinter.php',
|
||||||
'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php',
|
'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php',
|
||||||
'ArcanistSetConfigWorkflow' => 'workflow/ArcanistSetConfigWorkflow.php',
|
'ArcanistSetConfigWorkflow' => 'workflow/ArcanistSetConfigWorkflow.php',
|
||||||
'ArcanistSettings' => 'configuration/ArcanistSettings.php',
|
'ArcanistSettings' => 'configuration/ArcanistSettings.php',
|
||||||
|
@ -215,6 +216,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistPyLintLinter' => 'ArcanistLinter',
|
'ArcanistPyLintLinter' => 'ArcanistLinter',
|
||||||
'ArcanistRubyLinter' => 'ArcanistLinter',
|
'ArcanistRubyLinter' => 'ArcanistLinter',
|
||||||
'ArcanistRubyLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
'ArcanistRubyLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
||||||
|
'ArcanistScalaSBTLinter' => 'ArcanistLinter',
|
||||||
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
|
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
|
||||||
'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
|
|
|
@ -45,6 +45,9 @@ final class ComprehensiveLintEngine extends ArcanistLintEngine {
|
||||||
$linters[] = id(new ArcanistRubyLinter())
|
$linters[] = id(new ArcanistRubyLinter())
|
||||||
->setPaths(preg_grep('/\.rb$/', $paths));
|
->setPaths(preg_grep('/\.rb$/', $paths));
|
||||||
|
|
||||||
|
$linters[] = id(new ArcanistScalaSBTLinter())
|
||||||
|
->setPaths(preg_grep('/\.scala$/', $paths));
|
||||||
|
|
||||||
$linters[] = id(new ArcanistJSHintLinter())
|
$linters[] = id(new ArcanistJSHintLinter())
|
||||||
->setPaths(preg_grep('/\.js$/', $paths));
|
->setPaths(preg_grep('/\.js$/', $paths));
|
||||||
|
|
||||||
|
|
106
src/lint/linter/ArcanistScalaSBTLinter.php
Normal file
106
src/lint/linter/ArcanistScalaSBTLinter.php
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses `sbt compile` to detect various warnings/errors in Scala code.
|
||||||
|
*
|
||||||
|
* @group linter
|
||||||
|
*/
|
||||||
|
final class ArcanistScalaSBTLinter extends ArcanistLinter {
|
||||||
|
|
||||||
|
public function willLintPaths(array $paths) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinterName() {
|
||||||
|
return 'ScalaSBT';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLintSeverityMap() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLintNameMap() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRun() {
|
||||||
|
// Check if this looks like a SBT project. If it doesn't, throw, because
|
||||||
|
// we rely fairly heavily on `sbt compile` working, below. We don't want
|
||||||
|
// to call out to scalac ourselves, because then we'll end up in Class Path
|
||||||
|
// Hell. We let the build system handle this for us.
|
||||||
|
if (!Filesystem::pathExists('project/Build.scala') &&
|
||||||
|
!Filesystem::pathExists('build.sbt')) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"This directory does not appear to be maintained by SBT, as we can't ".
|
||||||
|
"seem to find a working build file (project/Build.scala or ".
|
||||||
|
"build.sbt).");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSBTPath() {
|
||||||
|
$sbt_bin = "sbt";
|
||||||
|
|
||||||
|
// Use the SBT prefix specified in the config file
|
||||||
|
$working_copy = $this->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue