Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13971707
D8988.id21344.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Referenced Files
None
Subscribers
None
D8988.id21344.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
@@ -84,6 +84,8 @@
'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php',
'ArcanistJSHintLinter' => 'lint/linter/ArcanistJSHintLinter.php',
'ArcanistJSHintLinterTestCase' => 'lint/linter/__tests__/ArcanistJSHintLinterTestCase.php',
+ 'ArcanistJSONLintLinter' => 'lint/linter/ArcanistJSONLintLinter.php',
+ 'ArcanistJSONLintLinterTestCase' => 'lint/linter/__tests__/ArcanistJSONLintLinterTestCase.php',
'ArcanistLandWorkflow' => 'workflow/ArcanistLandWorkflow.php',
'ArcanistLiberateWorkflow' => 'workflow/ArcanistLiberateWorkflow.php',
'ArcanistLintConsoleRenderer' => 'lint/renderer/ArcanistLintConsoleRenderer.php',
@@ -245,6 +247,8 @@
'ArcanistInstallCertificateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistJSHintLinter' => 'ArcanistExternalLinter',
'ArcanistJSHintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
+ 'ArcanistJSONLintLinter' => 'ArcanistExternalLinter',
+ 'ArcanistJSONLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistLandWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLintConsoleRenderer' => 'ArcanistLintRenderer',
diff --git a/src/lint/linter/ArcanistJSONLintLinter.php b/src/lint/linter/ArcanistJSONLintLinter.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/ArcanistJSONLintLinter.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * A linter for JSON files.
+ */
+final class ArcanistJSONLintLinter extends ArcanistExternalLinter {
+ public function getLinterName() {
+ return 'JSON';
+ }
+
+ public function getLinterConfigurationName() {
+ return 'jsonlint';
+ }
+
+ public function getDefaultBinary() {
+ return 'jsonlint';
+ }
+
+ public function getVersion() {
+ // NOTE: `jsonlint --version` returns a non-zero exit status.
+ list($err, $stdout) = exec_manual(
+ '%C --version',
+ $this->getExecutableCommand());
+
+ $matches = array();
+ if (preg_match('/^(?P<version>\d+\.\d+\.\d+)$/', $stdout, $matches)) {
+ $version = $matches['version'];
+ } else {
+ return false;
+ }
+ }
+
+ public function getInstallInstructions() {
+ return pht('Install jsonlint using `npm install -g jsonlint`.');
+ }
+
+ public function shouldExpectCommandErrors() {
+ return true;
+ }
+
+ public function supportsReadDataFromStdin() {
+ return true;
+ }
+
+ protected function getMandatoryFlags() {
+ return array(
+ '--compact',
+ );
+ }
+
+ protected function parseLinterOutput($path, $err, $stdout, $stderr) {
+ $lines = phutil_split_lines($stderr, false);
+
+ $messages = array();
+ foreach ($lines as $line) {
+ $matches = null;
+ $match = preg_match(
+ '/^(?:(?<path>.+): )?' .
+ 'line (?<line>\d+), col (?<column>\d+), ' .
+ '(?<description>.*)$/',
+ $line,
+ $matches);
+
+ if ($match) {
+ $message = new ArcanistLintMessage();
+ $message->setPath($path);
+ $message->setLine($matches['line']);
+ $message->setChar($matches['column']);
+ $message->setCode($this->getLinterName());
+ $message->setDescription(ucfirst($matches['description']));
+ $message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR);
+
+ $messages[] = $message;
+ }
+ }
+
+ if ($err && !$messages) {
+ return false;
+ }
+
+ return $messages;
+ }
+}
diff --git a/src/lint/linter/__tests__/ArcanistJSONLintLinterTestCase.php b/src/lint/linter/__tests__/ArcanistJSONLintLinterTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ArcanistJSONLintLinterTestCase.php
@@ -0,0 +1,12 @@
+<?php
+
+final class ArcanistJSONLintLinterTestCase
+ extends ArcanistArcanistLinterTestCase {
+
+ public function testJSONLintLinter() {
+ $this->executeTestsInDirectory(
+ dirname(__FILE__).'/jsonlint/',
+ new ArcanistJSONLintLinter());
+ }
+
+}
diff --git a/src/lint/linter/__tests__/jsonlint/1.lint-test b/src/lint/linter/__tests__/jsonlint/1.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/1.lint-test
@@ -0,0 +1,59 @@
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "" \u0022 %22 0x22 034 "",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"]
+~~~~~~~~~~
diff --git a/src/lint/linter/__tests__/jsonlint/10.lint-test b/src/lint/linter/__tests__/jsonlint/10.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/10.lint-test
@@ -0,0 +1,3 @@
+{"Extra value after close": true} "misplaced quoted value"
+~~~~~~~~~~
+error:1:33
diff --git a/src/lint/linter/__tests__/jsonlint/11.lint-test b/src/lint/linter/__tests__/jsonlint/11.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/11.lint-test
@@ -0,0 +1,3 @@
+{"Illegal expression": 1 + 2}
+~~~~~~~~~~
+error:1:24
diff --git a/src/lint/linter/__tests__/jsonlint/12.lint-test b/src/lint/linter/__tests__/jsonlint/12.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/12.lint-test
@@ -0,0 +1,3 @@
+{"Illegal invocation": alert()}
+~~~~~~~~~~
+error:1:22
diff --git a/src/lint/linter/__tests__/jsonlint/13.lint-test b/src/lint/linter/__tests__/jsonlint/13.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/13.lint-test
@@ -0,0 +1,3 @@
+{"Numbers cannot have leading zeroes": 013}
+~~~~~~~~~~
+error:1:38
diff --git a/src/lint/linter/__tests__/jsonlint/14.lint-test b/src/lint/linter/__tests__/jsonlint/14.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/14.lint-test
@@ -0,0 +1,3 @@
+{"Numbers cannot be hex": 0x14}
+~~~~~~~~~~
+error:1:25
diff --git a/src/lint/linter/__tests__/jsonlint/15.lint-test b/src/lint/linter/__tests__/jsonlint/15.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/15.lint-test
@@ -0,0 +1,3 @@
+["Illegal backslash escape: \x15"]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/16.lint-test b/src/lint/linter/__tests__/jsonlint/16.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/16.lint-test
@@ -0,0 +1,3 @@
+[\naked]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/17.lint-test b/src/lint/linter/__tests__/jsonlint/17.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/17.lint-test
@@ -0,0 +1,3 @@
+["Illegal backslash escape: \017"]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/19.lint-test b/src/lint/linter/__tests__/jsonlint/19.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/19.lint-test
@@ -0,0 +1,3 @@
+{"Missing colon" null}
+~~~~~~~~~~
+error:1:16
diff --git a/src/lint/linter/__tests__/jsonlint/2.lint-test b/src/lint/linter/__tests__/jsonlint/2.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/2.lint-test
@@ -0,0 +1,2 @@
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
+~~~~~~~~~~
diff --git a/src/lint/linter/__tests__/jsonlint/20.lint-test b/src/lint/linter/__tests__/jsonlint/20.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/20.lint-test
@@ -0,0 +1,3 @@
+{"Double colon":: null}
+~~~~~~~~~~
+error:1:16
diff --git a/src/lint/linter/__tests__/jsonlint/21.lint-test b/src/lint/linter/__tests__/jsonlint/21.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/21.lint-test
@@ -0,0 +1,3 @@
+{"Comma instead of colon", null}
+~~~~~~~~~~
+error:1:25
diff --git a/src/lint/linter/__tests__/jsonlint/22.lint-test b/src/lint/linter/__tests__/jsonlint/22.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/22.lint-test
@@ -0,0 +1,3 @@
+["Colon instead of comma": false]
+~~~~~~~~~~
+error:1:25
diff --git a/src/lint/linter/__tests__/jsonlint/23.lint-test b/src/lint/linter/__tests__/jsonlint/23.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/23.lint-test
@@ -0,0 +1,3 @@
+["Bad value", truth]
+~~~~~~~~~~
+error:1:13
diff --git a/src/lint/linter/__tests__/jsonlint/24.lint-test b/src/lint/linter/__tests__/jsonlint/24.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/24.lint-test
@@ -0,0 +1,3 @@
+['single quote']
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/25.lint-test b/src/lint/linter/__tests__/jsonlint/25.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/25.lint-test
@@ -0,0 +1,3 @@
+[" tab character in string "]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/26.lint-test b/src/lint/linter/__tests__/jsonlint/26.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/26.lint-test
@@ -0,0 +1,3 @@
+["tab\ character\ in\ string\ "]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/27.lint-test b/src/lint/linter/__tests__/jsonlint/27.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/27.lint-test
@@ -0,0 +1,4 @@
+["line
+break"]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/28.lint-test b/src/lint/linter/__tests__/jsonlint/28.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/28.lint-test
@@ -0,0 +1,4 @@
+["line\
+break"]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/29.lint-test b/src/lint/linter/__tests__/jsonlint/29.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/29.lint-test
@@ -0,0 +1,3 @@
+[0e]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/3.lint-test b/src/lint/linter/__tests__/jsonlint/3.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/3.lint-test
@@ -0,0 +1,7 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
+~~~~~~~~~~
diff --git a/src/lint/linter/__tests__/jsonlint/30.lint-test b/src/lint/linter/__tests__/jsonlint/30.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/30.lint-test
@@ -0,0 +1,3 @@
+[0e+]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/31.lint-test b/src/lint/linter/__tests__/jsonlint/31.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/31.lint-test
@@ -0,0 +1,3 @@
+[0e+-1]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/32.lint-test b/src/lint/linter/__tests__/jsonlint/32.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/32.lint-test
@@ -0,0 +1,3 @@
+{"Comma instead if closing brace": true,
+~~~~~~~~~~
+error:1:40
diff --git a/src/lint/linter/__tests__/jsonlint/33.lint-test b/src/lint/linter/__tests__/jsonlint/33.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/33.lint-test
@@ -0,0 +1,3 @@
+["mismatch"}
+~~~~~~~~~~
+error:1:11
diff --git a/src/lint/linter/__tests__/jsonlint/34.lint-test b/src/lint/linter/__tests__/jsonlint/34.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/34.lint-test
@@ -0,0 +1,3 @@
+{"extra brace": 1}}
+~~~~~~~~~~
+error:1:18
diff --git a/src/lint/linter/__tests__/jsonlint/4.lint-test b/src/lint/linter/__tests__/jsonlint/4.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/4.lint-test
@@ -0,0 +1,3 @@
+["extra comma",]
+~~~~~~~~~~
+error:1:15
diff --git a/src/lint/linter/__tests__/jsonlint/5.lint-test b/src/lint/linter/__tests__/jsonlint/5.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/5.lint-test
@@ -0,0 +1,3 @@
+["double extra comma",,]
+~~~~~~~~~~
+error:1:22
diff --git a/src/lint/linter/__tests__/jsonlint/6.lint-test b/src/lint/linter/__tests__/jsonlint/6.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/6.lint-test
@@ -0,0 +1,3 @@
+[, "<-- missing value"]
+~~~~~~~~~~
+error:1:1
diff --git a/src/lint/linter/__tests__/jsonlint/7.lint-test b/src/lint/linter/__tests__/jsonlint/7.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/7.lint-test
@@ -0,0 +1,3 @@
+["Comma after the close"],
+~~~~~~~~~~
+error:1:25
diff --git a/src/lint/linter/__tests__/jsonlint/8.lint-test b/src/lint/linter/__tests__/jsonlint/8.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/8.lint-test
@@ -0,0 +1,3 @@
+["Extra close"]]
+~~~~~~~~~~
+error:1:15
diff --git a/src/lint/linter/__tests__/jsonlint/9.lint-test b/src/lint/linter/__tests__/jsonlint/9.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/jsonlint/9.lint-test
@@ -0,0 +1,3 @@
+{"Extra comma": true,}
+~~~~~~~~~~
+error:1:21
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 18, 2:53 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6712342
Default Alt Text
D8988.id21344.diff (14 KB)
Attached To
Mode
D8988: Add a JSON linter.
Attached
Detach File
Event Timeline
Log In to Comment