Page MenuHomePhabricator

D12620.diff
No OneTemporary

D12620.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
@@ -85,6 +85,8 @@
'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php',
'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php',
'ArcanistGitHookPreReceiveWorkflow' => 'workflow/ArcanistGitHookPreReceiveWorkflow.php',
+ 'ArcanistGoFmtLinter' => 'lint/linter/ArcanistGoFmtLinter.php',
+ 'ArcanistGoFmtLinterTestCase' => 'lint/linter/__tests__/ArcanistGoFmtLinterTestCase.php',
'ArcanistGoLintLinter' => 'lint/linter/ArcanistGoLintLinter.php',
'ArcanistGoLintLinterTestCase' => 'lint/linter/__tests__/ArcanistGoLintLinterTestCase.php',
'ArcanistGoTestResultParser' => 'unit/parser/ArcanistGoTestResultParser.php',
@@ -285,6 +287,8 @@
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistGoFmtLinter' => 'ArcanistLinter',
+ 'ArcanistGoFmtLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistGoLintLinter' => 'ArcanistExternalLinter',
'ArcanistGoLintLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistGoTestResultParser' => 'ArcanistTestResultParser',
diff --git a/src/lint/linter/ArcanistGoFmtLinter.php b/src/lint/linter/ArcanistGoFmtLinter.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/ArcanistGoFmtLinter.php
@@ -0,0 +1,106 @@
+<?php
+
+final class ArcanistGoFmtLinter extends ArcanistLinter {
+
+ const LINT_GO_UNFORMATTED = 0;
+
+ public function getInfoName() {
+ return 'Go fmt';
+ }
+
+ public function getInfoURI() {
+ return 'https://golang.org/doc/install';
+ }
+
+ public function getInfoDescription() {
+ return pht(
+ 'Gofmt formats Go programs. It uses tabs (width = 8) '.
+ 'for indentation and blanks for alignment.');
+ }
+
+ public function getLinterName() {
+ return 'GOFMT';
+ }
+
+ public function getLinterConfigurationName() {
+ return 'gofmt';
+ }
+
+ public function getBinary() {
+ return 'gofmt';
+ }
+
+ protected function checkBinaryConfiguration() {
+ $binary = $this->getBinary();
+ if (!Filesystem::binaryExists($binary)) {
+ throw new ArcanistMissingLinterException(
+ sprintf(
+ "%s\n%s",
+ pht(
+ 'Unable to locate binary "%s" to run linter %s. You may need '.
+ 'to install the binary, or adjust your linter configuration.',
+ $binary,
+ get_class($this)),
+ pht(
+ 'TO INSTALL: %s',
+ $this->getInstallInstructions())));
+ }
+ }
+
+ public function getInstallInstructions() {
+ return pht(
+ 'Gofmt comes with Go, please '.
+ 'follow https://golang.org/doc/install to install go');
+ }
+
+ public function getLintNameMap() {
+ return array(
+ self::LINT_GO_UNFORMATTED => "File is not gofmt'd",
+ );
+ }
+
+ // Gofmt must run before any other linter for Go.
+ public function getLinterPriority() {
+ return 10;
+ }
+
+ public function lintPath($path) {
+ $this->checkBinaryConfiguration();
+
+ $data = $this->getData($path);
+ $future = new ExecFuture('%C', $this->getBinary());
+ $future->write($data);
+ list($err, $stdout, $stderr) = $future->resolve();
+ if (empty($stdout) && $err) {
+ throw new Exception(
+ sprintf(
+ "%s\n\nSTDOUT\n%s\n\nSTDERR\n%s",
+ pht('Linter failed to parse output!'),
+ $stdout,
+ $stderr));
+ }
+
+ if ($stdout !== $data) {
+ $lines = explode("\n", $data);
+ $formatted_lines = explode("\n", $stdout);
+ foreach ($lines as $line_idx => $line) {
+ if ($line != $formatted_lines[$line_idx]) {
+ $lines = array_slice($lines, $line_idx);
+ $formatted_lines = array_slice($formatted_lines, $line_idx);
+ break;
+ }
+ }
+
+ $this->raiseLintAtLine(
+ $line_idx + 1,
+ 1,
+ self::LINT_GO_UNFORMATTED,
+ pht(
+ '%s was not formatted correctly. Please setup your '.
+ 'editor to run gofmt on save', $path),
+ implode("\n", $lines),
+ implode("\n", $formatted_lines));
+ }
+ }
+
+}
diff --git a/src/lint/linter/__tests__/ArcanistGoFmtLinterTestCase.php b/src/lint/linter/__tests__/ArcanistGoFmtLinterTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/ArcanistGoFmtLinterTestCase.php
@@ -0,0 +1,7 @@
+<?php
+
+final class ArcanistGoFmtLinterTestCase extends ArcanistExternalLinterTestCase {
+ public function testLinter() {
+ $this->executeTestsInDirectory(dirname(__FILE__).'/gofmt/');
+ }
+}
diff --git a/src/lint/linter/__tests__/gofmt/big-program-with-many-issues.lint-test b/src/lint/linter/__tests__/gofmt/big-program-with-many-issues.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/gofmt/big-program-with-many-issues.lint-test
@@ -0,0 +1,32 @@
+package main
+
+import ("fmt")
+type Animal struct{Type string
+ Color string}
+
+func main() {a := &Animal{Type: "Dog", Color: "Gold",}
+
+
+
+
+
+fmt.Printf("%#v", *a)}
+~~~~~~~~~~
+error:3:1
+~~~~~~~~~~
+package main
+
+import (
+ "fmt"
+)
+
+type Animal struct {
+ Type string
+ Color string
+}
+
+func main() {
+ a := &Animal{Type: "Dog", Color: "Gold"}
+
+ fmt.Printf("%#v", *a)
+}
diff --git a/src/lint/linter/__tests__/gofmt/extra-new-line.lint-test b/src/lint/linter/__tests__/gofmt/extra-new-line.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/gofmt/extra-new-line.lint-test
@@ -0,0 +1,18 @@
+package main
+
+import "fmt"
+
+
+func main() {
+ fmt.Println("%d", 1)
+}
+~~~~~~~~~~
+error:5:1
+~~~~~~~~~~
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("%d", 1)
+}
diff --git a/src/lint/linter/__tests__/gofmt/space-instead-of-tab.lint-test b/src/lint/linter/__tests__/gofmt/space-instead-of-tab.lint-test
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/__tests__/gofmt/space-instead-of-tab.lint-test
@@ -0,0 +1,17 @@
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("%d", 1)
+}
+~~~~~~~~~~
+error:6:1
+~~~~~~~~~~
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("%d", 1)
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 10:59 AM (1 d, 6 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6727993
Default Alt Text
D12620.diff (6 KB)

Event Timeline