Page MenuHomePhabricator

D10370.id24968.diff
No OneTemporary

D10370.id24968.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -132,6 +132,8 @@
'ArcanistPEP8LinterTestCase' => 'lint/linter/__tests__/ArcanistPEP8LinterTestCase.php',
'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php',
'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php',
+ 'ArcanistPhpLinter' => 'lint/linter/ArcanistPhpLinter.php',
+ 'ArcanistPhpLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpLinterTestCase.php',
'ArcanistPhpcsLinter' => 'lint/linter/ArcanistPhpcsLinter.php',
'ArcanistPhpcsLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpcsLinterTestCase.php',
'ArcanistPhrequentWorkflow' => 'workflow/ArcanistPhrequentWorkflow.php',
@@ -313,6 +315,8 @@
'ArcanistPEP8LinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPasteWorkflow' => 'ArcanistWorkflow',
'ArcanistPatchWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistPhpLinter' => 'ArcanistExternalLinter',
+ 'ArcanistPhpLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPhpcsLinter' => 'ArcanistExternalLinter',
'ArcanistPhpcsLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPhrequentWorkflow' => 'ArcanistWorkflow',
diff --git a/src/lint/linter/ArcanistPhpLinter.php b/src/lint/linter/ArcanistPhpLinter.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/ArcanistPhpLinter.php
@@ -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();
+ }
+
+}
diff --git a/src/lint/linter/__tests__/ArcanistPhpLinterTestCase.php b/src/lint/linter/__tests__/ArcanistPhpLinterTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ArcanistPhpLinterTestCase.php
@@ -0,0 +1,11 @@
+<?php
+
+final class ArcanistPhpLinterTestCase extends ArcanistArcanistLinterTestCase {
+
+ public function testPHPLint() {
+ $this->executeTestsInDirectory(
+ dirname(__FILE__).'/php/',
+ new ArcanistPhpLinter());
+ }
+
+}
diff --git a/src/lint/linter/__tests__/php/fatal.lint-test b/src/lint/linter/__tests__/php/fatal.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/php/fatal.lint-test
@@ -0,0 +1,7 @@
+<?php
+
+function f() {
+ $this = "cannot be re-assigned";
+}
+~~~~~~~~~
+error:4:
diff --git a/src/lint/linter/__tests__/php/no-errors.lint-test b/src/lint/linter/__tests__/php/no-errors.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/php/no-errors.lint-test
@@ -0,0 +1,6 @@
+<?php
+
+function f() {
+ return "foobar";
+}
+~~~~~~~~~~
diff --git a/src/lint/linter/__tests__/php/syntax.lint-test b/src/lint/linter/__tests__/php/syntax.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/php/syntax.lint-test
@@ -0,0 +1,7 @@
+<?php
+
+function f() {
+ this is bad syntax;
+}
+~~~~~~~~~
+error:4:

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 19, 4:13 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6717560
Default Alt Text
D10370.id24968.diff (4 KB)

Event Timeline