Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13974130
D10370.id24968.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D10370.id24968.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D10370: Adding php -l linter
Attached
Detach File
Event Timeline
Log In to Comment