mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Adding php -l linter
Summary: Adds a linter that checks php files for syntax errors using php -l Test Plan: Add a section to your .arclint file similar to: ``` "php": { "type": "php", "include": "(\\.php$)" } ``` Then run arc lint on a php file with a syntax error. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: epriestley, jacobwalker0814, Korvin Differential Revision: https://secure.phabricator.com/D10370
This commit is contained in:
parent
e4bbcaf8f7
commit
9fc8a2f61b
6 changed files with 120 additions and 0 deletions
|
@ -132,6 +132,8 @@ phutil_register_library_map(array(
|
||||||
'ArcanistPEP8LinterTestCase' => 'lint/linter/__tests__/ArcanistPEP8LinterTestCase.php',
|
'ArcanistPEP8LinterTestCase' => 'lint/linter/__tests__/ArcanistPEP8LinterTestCase.php',
|
||||||
'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php',
|
'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php',
|
||||||
'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php',
|
'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php',
|
||||||
|
'ArcanistPhpLinter' => 'lint/linter/ArcanistPhpLinter.php',
|
||||||
|
'ArcanistPhpLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpLinterTestCase.php',
|
||||||
'ArcanistPhpcsLinter' => 'lint/linter/ArcanistPhpcsLinter.php',
|
'ArcanistPhpcsLinter' => 'lint/linter/ArcanistPhpcsLinter.php',
|
||||||
'ArcanistPhpcsLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpcsLinterTestCase.php',
|
'ArcanistPhpcsLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpcsLinterTestCase.php',
|
||||||
'ArcanistPhrequentWorkflow' => 'workflow/ArcanistPhrequentWorkflow.php',
|
'ArcanistPhrequentWorkflow' => 'workflow/ArcanistPhrequentWorkflow.php',
|
||||||
|
@ -313,6 +315,8 @@ phutil_register_library_map(array(
|
||||||
'ArcanistPEP8LinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
'ArcanistPEP8LinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
||||||
'ArcanistPasteWorkflow' => 'ArcanistWorkflow',
|
'ArcanistPasteWorkflow' => 'ArcanistWorkflow',
|
||||||
'ArcanistPatchWorkflow' => 'ArcanistWorkflow',
|
'ArcanistPatchWorkflow' => 'ArcanistWorkflow',
|
||||||
|
'ArcanistPhpLinter' => 'ArcanistExternalLinter',
|
||||||
|
'ArcanistPhpLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
||||||
'ArcanistPhpcsLinter' => 'ArcanistExternalLinter',
|
'ArcanistPhpcsLinter' => 'ArcanistExternalLinter',
|
||||||
'ArcanistPhpcsLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
'ArcanistPhpcsLinterTestCase' => 'ArcanistArcanistLinterTestCase',
|
||||||
'ArcanistPhrequentWorkflow' => 'ArcanistWorkflow',
|
'ArcanistPhrequentWorkflow' => 'ArcanistWorkflow',
|
||||||
|
|
85
src/lint/linter/ArcanistPhpLinter.php
Normal file
85
src/lint/linter/ArcanistPhpLinter.php
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses "php -l" to detect syntax errors in PHP code.
|
||||||
|
*/
|
||||||
|
final class ArcanistPhpLinter extends ArcanistExternalLinter {
|
||||||
|
|
||||||
|
public function getInfoName() {
|
||||||
|
return 'php -l';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInfoURI() {
|
||||||
|
return 'http://php.net/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInfoDescription() {
|
||||||
|
return pht(
|
||||||
|
'Checks for syntax errors in php files.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinterName() {
|
||||||
|
return 'PHP';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinterConfigurationName() {
|
||||||
|
return 'php';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMandatoryFlags() {
|
||||||
|
return array('-l');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInstallInstructions() {
|
||||||
|
return pht('Install PHP.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultBinary() {
|
||||||
|
return 'php';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVersion() {
|
||||||
|
list($stdout) = execx('%C --version', $this->getExecutableCommand());
|
||||||
|
|
||||||
|
$matches = array();
|
||||||
|
$regex = '/^PHP (?P<version>\d+\.\d+\.\d+)\b/';
|
||||||
|
if (preg_match($regex, $stdout, $matches)) {
|
||||||
|
return $matches['version'];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldExpectCommandErrors() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsReadDataFromStdin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseLinterOutput($path, $err, $stdout, $stderr) {
|
||||||
|
// Older versions of php had both on $stdout, newer ones split it
|
||||||
|
// Combine $stdout and $stderr for consistency
|
||||||
|
$stdout = $stderr."\n".$stdout;
|
||||||
|
$matches = array();
|
||||||
|
$regex = '/PHP (?<type>.+?) error:\s+(?<error>.*?)\s+in\s+(?<file>.*?)'.
|
||||||
|
'\s+on line\s+(?<line>\d*)/';
|
||||||
|
if (preg_match($regex, $stdout, $matches)) {
|
||||||
|
$type = strtolower($matches['type']);
|
||||||
|
$message = new ArcanistLintMessage();
|
||||||
|
$message->setPath($matches['file']);
|
||||||
|
$message->setLine($matches['line']);
|
||||||
|
$message->setCode('php.'.$type);
|
||||||
|
$message->setDescription('This file contains a '.$type.' error: '.
|
||||||
|
$matches['error'].' on line '.$matches['line']);
|
||||||
|
$message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR);
|
||||||
|
|
||||||
|
// php -l only returns the first error
|
||||||
|
return array($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
src/lint/linter/__tests__/ArcanistPhpLinterTestCase.php
Normal file
11
src/lint/linter/__tests__/ArcanistPhpLinterTestCase.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistPhpLinterTestCase extends ArcanistArcanistLinterTestCase {
|
||||||
|
|
||||||
|
public function testPHPLint() {
|
||||||
|
$this->executeTestsInDirectory(
|
||||||
|
dirname(__FILE__).'/php/',
|
||||||
|
new ArcanistPhpLinter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
7
src/lint/linter/__tests__/php/fatal.lint-test
Normal file
7
src/lint/linter/__tests__/php/fatal.lint-test
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
$this = "cannot be re-assigned";
|
||||||
|
}
|
||||||
|
~~~~~~~~~
|
||||||
|
error:4:
|
6
src/lint/linter/__tests__/php/no-errors.lint-test
Normal file
6
src/lint/linter/__tests__/php/no-errors.lint-test
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
return "foobar";
|
||||||
|
}
|
||||||
|
~~~~~~~~~~
|
7
src/lint/linter/__tests__/php/syntax.lint-test
Normal file
7
src/lint/linter/__tests__/php/syntax.lint-test
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
this is bad syntax;
|
||||||
|
}
|
||||||
|
~~~~~~~~~
|
||||||
|
error:4:
|
Loading…
Reference in a new issue