1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-21 22:32:41 +01:00

Make ruby -wc a linter in Arcanist

Summary: Add `ruby -wc` as a linter and raise Error whenever there's a syntax error

Test Plan: Just a few dumb unit tests.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D3447
This commit is contained in:
Leah Xue 2012-09-06 11:50:15 -07:00
parent 9dd1a87066
commit 03e5d651b5
8 changed files with 177 additions and 1 deletions

View file

@ -1,7 +1,7 @@
{ {
"project_id" : "arcanist", "project_id" : "arcanist",
"conduit_uri" : "https://secure.phabricator.com/", "conduit_uri" : "https://secure.phabricator.com/",
"lint_engine" : "PhutilLintEngine", "lint_engine" : "ComprehensiveLintEngine",
"unit_engine" : "PhutilUnitTestEngine", "unit_engine" : "PhutilUnitTestEngine",
"copyright_holder" : "Facebook, Inc.", "copyright_holder" : "Facebook, Inc.",
"phutil_libraries" : { "phutil_libraries" : {

View file

@ -101,6 +101,8 @@ phutil_register_library_map(array(
'ArcanistPyFlakesLinter' => 'lint/linter/ArcanistPyFlakesLinter.php', 'ArcanistPyFlakesLinter' => 'lint/linter/ArcanistPyFlakesLinter.php',
'ArcanistPyLintLinter' => 'lint/linter/ArcanistPyLintLinter.php', 'ArcanistPyLintLinter' => 'lint/linter/ArcanistPyLintLinter.php',
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php', 'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.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',
@ -208,6 +210,8 @@ phutil_register_library_map(array(
'ArcanistPhutilTestTerminatedException' => 'Exception', 'ArcanistPhutilTestTerminatedException' => 'Exception',
'ArcanistPyFlakesLinter' => 'ArcanistLinter', 'ArcanistPyFlakesLinter' => 'ArcanistLinter',
'ArcanistPyLintLinter' => 'ArcanistLinter', 'ArcanistPyLintLinter' => 'ArcanistLinter',
'ArcanistRubyLinter' => 'ArcanistLinter',
'ArcanistRubyLinterTestCase' => 'ArcanistLinterTestCase',
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter', 'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow',

View file

@ -81,6 +81,7 @@ final class ComprehensiveLintEngine extends ArcanistLintEngine {
$linters = array_merge($linters, $this->buildLicenseLinters($paths)); $linters = array_merge($linters, $this->buildLicenseLinters($paths));
$linters = array_merge($linters, $this->buildPythonLinters($paths)); $linters = array_merge($linters, $this->buildPythonLinters($paths));
$linters = array_merge($linters, $this->buildRubyLinters($paths));
$linters = array_merge($linters, $this->buildJSLinters($paths)); $linters = array_merge($linters, $this->buildJSLinters($paths));
return $linters; return $linters;
@ -120,6 +121,20 @@ final class ComprehensiveLintEngine extends ArcanistLintEngine {
return $linters; return $linters;
} }
public function buildRubyLinters($paths) {
$ruby_linter = new ArcanistRubyLinter();
$linters = array();
$linters[] = $ruby_linter;
foreach ($paths as $path) {
if (preg_match('/\.rb$/', $path)) {
$ruby_linter->addPath($path);
$ruby_linter->addData($path, $this->loadData($path));
}
}
return $linters;
}
public function buildJSLinters($paths) { public function buildJSLinters($paths) {
$js_linter = new ArcanistJSHintLinter(); $js_linter = new ArcanistJSHintLinter();

View file

@ -0,0 +1,103 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Uses "Ruby" to detect various errors in Ruby code.
*
* @group linter
*/
final class ArcanistRubyLinter extends ArcanistLinter {
public function willLintPaths(array $paths) {
return;
}
public function getLinterName() {
return 'Ruby';
}
public function getLintSeverityMap() {
return array();
}
public function getLintNameMap() {
return array();
}
private function getRubyPath() {
$ruby_bin = "ruby";
// Use the Ruby prefix specified in the config file
$working_copy = $this->getEngine()->getWorkingCopy();
$prefix = $working_copy->getConfig('lint.ruby.prefix');
if ($prefix !== null) {
$ruby_bin = $prefix . $ruby_bin;
}
if (!Filesystem::pathExists($ruby_bin)) {
list($err) = exec_manual('which %s', $ruby_bin);
if ($err) {
throw new ArcanistUsageException(
"Ruby does not appear to be installed on this system.".
"Install it or add ".
"'lint.ruby.prefix' in your .arcconfig to point to the directory ".
"where it resides.");
}
}
return $ruby_bin;
}
private function getMessageCodeSeverity($code) {
return ArcanistLintSeverity::SEVERITY_ERROR;
}
public function lintPath($path) {
$rubyp = $this->getRubyPath();
$f = new ExecFuture("%s -wc", $rubyp);
$f->write($this->getData($path));
list($err, $stdout, $stderr) = $f->resolve();
if ($err === 0 ) {
return;
}
$lines = explode("\n", $stderr);
$messages = array();
foreach ($lines as $line) {
$matches = null;
if (!preg_match("/(.*?):(\d+): (.*?)$/", $line, $matches)) {
continue;
}
foreach ($matches as $key => $match) {
$matches[$key] = trim($match);
}
$code = head(explode(',', $matches[3]));
$message = new ArcanistLintMessage();
$message->setPath($path);
$message->setLine($matches[2]);
$message->setName($this->getLinterName() . " " . $code);
$message->setDescription($matches[3]);
$message->setSeverity($this->getMessageCodeSeverity($code));
$this->addLintMessage($message);
}
}
}

View file

@ -0,0 +1,36 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Test cases for @{class:ArcanistRubyLinter}.
*
* @group testcase
*/
final class ArcanistRubyLinterTestCase extends ArcanistLinterTestCase {
public function testRubyLint() {
$linter = new ArcanistRubyLinter();
$working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
return $this->executeTestsInDirectory(
dirname(__FILE__).'/ruby/',
$linter,
$working_copy);
}
}

View file

@ -0,0 +1,4 @@
def hello()
puts "hello world"
~~~~~~~~~~
error:2:

View file

@ -0,0 +1,4 @@
def asdf()
puts "semicolons are ok";
end
~~~~~~~~~~

View file

@ -0,0 +1,10 @@
# ruby -wc says syntax ok
# ruby -w says blah.rb:2: undefined local variable or method `index' for main:Object (NameError)
if index < 0 and $VERBOSE
$stderr.puts "warning: index is a negative number"
if $DEBUG
$stderr.puts "index value: #{index.inspect}"
$stderr.puts "array state: #{array.inspect}"
end
end
~~~~~~~~~~