From 4f68773ba5e7511474601a3c8196f2531d1e5649 Mon Sep 17 00:00:00 2001 From: Peter Trifanov Date: Mon, 15 Jan 2024 22:12:24 +0100 Subject: [PATCH 01/11] Support gofmt --- README.md | 1 + gradle/special-tests.gradle | 1 + .../diffplug/spotless/go/GofmtFormatStep.java | 90 +++++++++++++++++++ .../gradle/spotless/FormatExtension.java | 28 ++++++ .../gradle/spotless/GoGradleTest.java | 41 +++++++++ .../com/diffplug/spotless/tag/GofmtTest.java | 30 +++++++ testlib/src/main/resources/go/gofmt/go.clean | 14 +++ testlib/src/main/resources/go/gofmt/go.dirty | 14 +++ .../spotless/go/GofmtFormatStepTest.java | 17 ++++ 9 files changed, 236 insertions(+) create mode 100644 lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java create mode 100644 plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java create mode 100644 testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java create mode 100644 testlib/src/main/resources/go/gofmt/go.clean create mode 100644 testlib/src/main/resources/go/gofmt/go.dirty create mode 100644 testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java diff --git a/README.md b/README.md index 4515eaf0a1..2020bbafa7 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ lib('antlr4.Antlr4FormatterStep') +'{{yes}} | {{yes}} lib('biome.BiomeStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', lib('cpp.ClangFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |', extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', +lib('go.GofmtFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |', lib('gherkin.GherkinUtilsStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', diff --git a/gradle/special-tests.gradle b/gradle/special-tests.gradle index ae9da9a06e..7da0324ab7 100644 --- a/gradle/special-tests.gradle +++ b/gradle/special-tests.gradle @@ -3,6 +3,7 @@ def special = [ 'Black', 'Buf', 'Clang', + 'gofmt', 'Npm', 'Shfmt' ] diff --git a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java new file mode 100644 index 0000000000..fd3a066f7c --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java @@ -0,0 +1,90 @@ +package com.diffplug.spotless.go; + +import com.diffplug.spotless.ForeignExe; +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ProcessRunner; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Note: gofmt doesn't have a version flag, because it's part of standard Go distribution. + * So `go` executable can be used to determine base path and version, and path to gofmt can be built from it. + */ +public class GofmtFormatStep { + public static String name() { + return "gofmt"; + } + + public static String defaultVersion() { + return "1.20.0"; + } + + private final String version; + private final @Nullable String pathToExe; + + private GofmtFormatStep(String version, String pathToExe) { + this.version = version; + this.pathToExe = pathToExe; + } + + public static GofmtFormatStep withVersion(String version) { + return new GofmtFormatStep(version, null); + } + + public GofmtFormatStep withGoExecutable(String pathToExe) { + return new GofmtFormatStep(version, pathToExe); + } + + public FormatterStep create() { + return FormatterStep.createLazy(name(), this::createState, GofmtFormatStep.State::toFunc); + } + + private State createState() throws IOException, InterruptedException { + String howToInstall = "gofmt is a part of standard go distribution. If spotless can't discover it automatically, " + + "you can point Spotless to the go binary with {@code pathToExe('/path/to/go')}"; + final ForeignExe exe = ForeignExe.nameAndVersion("go", version) + .pathToExe(pathToExe) + .versionFlag("version") + .fixCantFind(howToInstall) + .fixWrongVersion( + "You can tell Spotless to use the version you already have with {@code gofmt('{versionFound}')}" + + "or you can install the currently specified Go version, {version}.\n" + howToInstall); + return new State(this, exe); + } + + @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") + static class State implements Serializable { + private static final long serialVersionUID = -1825662355363926318L; + // used for up-to-date checks and caching + final String version; + final transient ForeignExe exe; + + public State(GofmtFormatStep step, ForeignExe goExecutable) { + this.version = step.version; + this.exe = Objects.requireNonNull(goExecutable); + } + + String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException { + final List processArgs = new ArrayList<>(); + String pathToGoBinary = exe.confirmVersionAndGetAbsolutePath(); + String pathToGoFmt = Path.of(pathToGoBinary).getParent().resolve("gofmt").toString(); + processArgs.add(pathToGoFmt); + return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8); + } + + FormatterFunc.Closeable toFunc() { + ProcessRunner runner = new ProcessRunner(); + return FormatterFunc.Closeable.of(runner, this::format); + } + } +} diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index eae8ac667d..c3eaef5628 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -36,6 +36,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; +import com.diffplug.spotless.go.GofmtFormatStep; import org.gradle.api.Action; import org.gradle.api.GradleException; import org.gradle.api.Project; @@ -956,6 +957,33 @@ public EclipseWtpConfig eclipseWtp(EclipseWtpFormatterStep type, String version) return new EclipseWtpConfig(type, version); } + public class GofmtConfig { + GofmtFormatStep stepCfg; + + public GofmtConfig(String version) { + stepCfg = (GofmtFormatStep) GofmtFormatStep.withVersion(version).create(); + addStep(createStep()); + } + + public GofmtConfig withGoExecutable(String pathToGo) { + stepCfg = stepCfg.withGoExecutable(pathToGo); + replaceStep(createStep()); + return this; + } + + private FormatterStep createStep() { + return stepCfg.create(); + } + } + + public GofmtConfig gofmt() { + return new GofmtConfig(GofmtFormatStep.defaultVersion()); + } + + public GofmtConfig gofmt(String version) { + return new GofmtConfig(version); + } + /** *
 	 * spotless {
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
new file mode 100644
index 0000000000..3488462580
--- /dev/null
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020-2021 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.gradle.spotless;
+
+import com.diffplug.spotless.tag.GofmtTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+@GofmtTest
+class GoGradleTest extends GradleIntegrationHarness {
+	@Test
+	void gofmt() throws IOException {
+		setFile("build.gradle").toLines(
+				"plugins {",
+				"  id 'com.diffplug.spotless'",
+				"}",
+				"spotless {",
+				"  format 'go' {",
+				"    target 'src/**/*.go'",
+				"    gofmt()",
+				"  }",
+				"}");
+		setFile("src/test.go").toResource("go/gofmt/go.dirty");
+		gradleRunner().withArguments("spotlessApply").build();
+		assertFile("src/test.go").sameAsResource("go/gofmt/go.clean");
+	}
+}
diff --git a/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java b/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java
new file mode 100644
index 0000000000..90091c1d69
--- /dev/null
+++ b/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.spotless.tag;
+
+import org.junit.jupiter.api.Tag;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Target({TYPE, METHOD})
+@Retention(RUNTIME)
+@Tag("gofmt")
+public @interface GofmtTest {}
diff --git a/testlib/src/main/resources/go/gofmt/go.clean b/testlib/src/main/resources/go/gofmt/go.clean
new file mode 100644
index 0000000000..321185cd76
--- /dev/null
+++ b/testlib/src/main/resources/go/gofmt/go.clean
@@ -0,0 +1,14 @@
+package main
+
+import "fmt"
+
+func split(sum int) (x int, y int) {
+	x = sum * 4 / 9
+	y = sum - x
+	return
+}
+
+func main() {
+	fmt.Println(
+		split(17))
+}
diff --git a/testlib/src/main/resources/go/gofmt/go.dirty b/testlib/src/main/resources/go/gofmt/go.dirty
new file mode 100644
index 0000000000..f1f9adaca7
--- /dev/null
+++ b/testlib/src/main/resources/go/gofmt/go.dirty
@@ -0,0 +1,14 @@
+package main
+
+import "fmt"
+
+func split (sum int) (x int ,  y int) {
+	x = sum   * 4 / 9
+	y    = sum - x
+	return
+}
+
+func main() {
+	fmt.Println(
+  split(17))
+}
diff --git a/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java b/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java
new file mode 100644
index 0000000000..6d35336730
--- /dev/null
+++ b/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java
@@ -0,0 +1,17 @@
+package com.diffplug.spotless.go;
+
+import com.diffplug.spotless.ResourceHarness;
+import com.diffplug.spotless.StepHarness;
+import com.diffplug.spotless.tag.GofmtTest;
+import org.junit.jupiter.api.Test;
+
+@GofmtTest
+public class GofmtFormatStepTest extends ResourceHarness {
+    @Test
+    void test() {
+        try (StepHarness harness = StepHarness.forStep(GofmtFormatStep.withVersion("go1.21.5").create())) {
+                harness.testResource("go/gofmt/go.dirty", "go/gofmt/go.clean")
+                    .close();
+        }
+    }
+}

From 2453b4fbcd01444e8a16efe50c6b7cd11ef06214 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Mon, 15 Jan 2024 22:27:37 +0100
Subject: [PATCH 02/11] Run `spotlessApply`

---
 .../diffplug/spotless/go/GofmtFormatStep.java | 163 ++++++++++--------
 .../gradle/spotless/FormatExtension.java      |   4 +-
 .../gradle/spotless/GoGradleTest.java         |   7 +-
 .../com/diffplug/spotless/tag/GofmtTest.java  |  10 +-
 .../spotless/go/GofmtFormatStepTest.java      |  32 +++-
 5 files changed, 125 insertions(+), 91 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
index fd3a066f7c..82cc4956de 100644
--- a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
@@ -1,12 +1,20 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.diffplug.spotless.go;
 
-import com.diffplug.spotless.ForeignExe;
-import com.diffplug.spotless.FormatterFunc;
-import com.diffplug.spotless.FormatterStep;
-import com.diffplug.spotless.ProcessRunner;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-import javax.annotation.Nullable;
 import java.io.File;
 import java.io.IOException;
 import java.io.Serializable;
@@ -16,75 +24,84 @@
 import java.util.List;
 import java.util.Objects;
 
+import javax.annotation.Nullable;
+
+import com.diffplug.spotless.ForeignExe;
+import com.diffplug.spotless.FormatterFunc;
+import com.diffplug.spotless.FormatterStep;
+import com.diffplug.spotless.ProcessRunner;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
 /**
  * Note: gofmt doesn't have a version flag, because it's part of standard Go distribution.
  * So `go` executable can be used to determine base path and version, and path to gofmt can be built from it.
  */
 public class GofmtFormatStep {
-    public static String name() {
-        return "gofmt";
-    }
-
-    public static String defaultVersion() {
-        return "1.20.0";
-    }
-
-    private final String version;
-    private final @Nullable String pathToExe;
-
-    private GofmtFormatStep(String version, String pathToExe) {
-        this.version = version;
-        this.pathToExe = pathToExe;
-    }
-
-    public static GofmtFormatStep withVersion(String version) {
-        return new GofmtFormatStep(version, null);
-    }
-
-    public GofmtFormatStep withGoExecutable(String pathToExe) {
-        return new GofmtFormatStep(version, pathToExe);
-    }
-
-    public FormatterStep create() {
-        return FormatterStep.createLazy(name(), this::createState, GofmtFormatStep.State::toFunc);
-    }
-
-    private State createState() throws IOException, InterruptedException {
-        String howToInstall = "gofmt is a part of standard go distribution. If spotless can't discover it automatically, " +
-                "you can point Spotless to the go binary with {@code pathToExe('/path/to/go')}";
-        final ForeignExe exe = ForeignExe.nameAndVersion("go", version)
-                .pathToExe(pathToExe)
-                .versionFlag("version")
-                .fixCantFind(howToInstall)
-                .fixWrongVersion(
-                        "You can tell Spotless to use the version you already have with {@code gofmt('{versionFound}')}" +
-                                "or you can install the currently specified Go version, {version}.\n" + howToInstall);
-        return new State(this, exe);
-    }
-
-    @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
-    static class State implements Serializable {
-        private static final long serialVersionUID = -1825662355363926318L;
-        // used for up-to-date checks and caching
-        final String version;
-        final transient ForeignExe exe;
-
-        public State(GofmtFormatStep step, ForeignExe goExecutable) {
-            this.version = step.version;
-            this.exe = Objects.requireNonNull(goExecutable);
-        }
-
-        String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
-            final List processArgs = new ArrayList<>();
-            String pathToGoBinary = exe.confirmVersionAndGetAbsolutePath();
-            String pathToGoFmt = Path.of(pathToGoBinary).getParent().resolve("gofmt").toString();
-            processArgs.add(pathToGoFmt);
-            return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8);
-        }
-
-        FormatterFunc.Closeable toFunc() {
-            ProcessRunner runner = new ProcessRunner();
-            return FormatterFunc.Closeable.of(runner, this::format);
-        }
-    }
+	public static String name() {
+		return "gofmt";
+	}
+
+	public static String defaultVersion() {
+		return "1.20.0";
+	}
+
+	private final String version;
+	private final @Nullable String pathToExe;
+
+	private GofmtFormatStep(String version, String pathToExe) {
+		this.version = version;
+		this.pathToExe = pathToExe;
+	}
+
+	public static GofmtFormatStep withVersion(String version) {
+		return new GofmtFormatStep(version, null);
+	}
+
+	public GofmtFormatStep withGoExecutable(String pathToExe) {
+		return new GofmtFormatStep(version, pathToExe);
+	}
+
+	public FormatterStep create() {
+		return FormatterStep.createLazy(name(), this::createState, GofmtFormatStep.State::toFunc);
+	}
+
+	private State createState() throws IOException, InterruptedException {
+		String howToInstall = "gofmt is a part of standard go distribution. If spotless can't discover it automatically, " +
+				"you can point Spotless to the go binary with {@code pathToExe('/path/to/go')}";
+		final ForeignExe exe = ForeignExe.nameAndVersion("go", version)
+				.pathToExe(pathToExe)
+				.versionFlag("version")
+				.fixCantFind(howToInstall)
+				.fixWrongVersion(
+						"You can tell Spotless to use the version you already have with {@code gofmt('{versionFound}')}" +
+								"or you can install the currently specified Go version, {version}.\n" + howToInstall);
+		return new State(this, exe);
+	}
+
+	@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
+	static class State implements Serializable {
+		private static final long serialVersionUID = -1825662355363926318L;
+		// used for up-to-date checks and caching
+		final String version;
+		final transient ForeignExe exe;
+
+		public State(GofmtFormatStep step, ForeignExe goExecutable) {
+			this.version = step.version;
+			this.exe = Objects.requireNonNull(goExecutable);
+		}
+
+		String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
+			final List processArgs = new ArrayList<>();
+			String pathToGoBinary = exe.confirmVersionAndGetAbsolutePath();
+			String pathToGoFmt = Path.of(pathToGoBinary).getParent().resolve("gofmt").toString();
+			processArgs.add(pathToGoFmt);
+			return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8);
+		}
+
+		FormatterFunc.Closeable toFunc() {
+			ProcessRunner runner = new ProcessRunner();
+			return FormatterFunc.Closeable.of(runner, this::format);
+		}
+	}
 }
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index c3eaef5628..a19918796e 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 DiffPlug
+ * Copyright 2016-2024 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,7 +36,6 @@
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 
-import com.diffplug.spotless.go.GofmtFormatStep;
 import org.gradle.api.Action;
 import org.gradle.api.GradleException;
 import org.gradle.api.Project;
@@ -66,6 +65,7 @@
 import com.diffplug.spotless.generic.ReplaceRegexStep;
 import com.diffplug.spotless.generic.ReplaceStep;
 import com.diffplug.spotless.generic.TrimTrailingWhitespaceStep;
+import com.diffplug.spotless.go.GofmtFormatStep;
 import com.diffplug.spotless.npm.NpmPathResolver;
 import com.diffplug.spotless.npm.PrettierFormatterStep;
 import com.diffplug.spotless.rome.BiomeFlavor;
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
index 3488462580..1d5fea7e41 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 DiffPlug
+ * Copyright 2020-2024 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,10 +15,11 @@
  */
 package com.diffplug.gradle.spotless;
 
-import com.diffplug.spotless.tag.GofmtTest;
+import java.io.IOException;
+
 import org.junit.jupiter.api.Test;
 
-import java.io.IOException;
+import com.diffplug.spotless.tag.GofmtTest;
 
 @GofmtTest
 class GoGradleTest extends GradleIntegrationHarness {
diff --git a/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java b/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java
index 90091c1d69..6228a84895 100644
--- a/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java
+++ b/testlib/src/main/java/com/diffplug/spotless/tag/GofmtTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 DiffPlug
+ * Copyright 2021-2024 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,14 +15,14 @@
  */
 package com.diffplug.spotless.tag;
 
-import org.junit.jupiter.api.Tag;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import org.junit.jupiter.api.Tag;
 
 @Target({TYPE, METHOD})
 @Retention(RUNTIME)
diff --git a/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java b/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java
index 6d35336730..c9158088fa 100644
--- a/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/go/GofmtFormatStepTest.java
@@ -1,17 +1,33 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.diffplug.spotless.go;
 
+import org.junit.jupiter.api.Test;
+
 import com.diffplug.spotless.ResourceHarness;
 import com.diffplug.spotless.StepHarness;
 import com.diffplug.spotless.tag.GofmtTest;
-import org.junit.jupiter.api.Test;
 
 @GofmtTest
 public class GofmtFormatStepTest extends ResourceHarness {
-    @Test
-    void test() {
-        try (StepHarness harness = StepHarness.forStep(GofmtFormatStep.withVersion("go1.21.5").create())) {
-                harness.testResource("go/gofmt/go.dirty", "go/gofmt/go.clean")
-                    .close();
-        }
-    }
+	@Test
+	void test() {
+		try (StepHarness harness = StepHarness.forStep(GofmtFormatStep.withVersion("go1.21.5").create())) {
+			harness.testResource("go/gofmt/go.dirty", "go/gofmt/go.clean")
+					.close();
+		}
+	}
 }

From 18f1b3c4dc18ab666ee6911499185b5afdda8617 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Mon, 15 Jan 2024 22:29:57 +0100
Subject: [PATCH 03/11] Update `CHANGES.md` and `plugin-gradle/CHANGES.md`

---
 CHANGES.md               | 1 +
 plugin-gradle/CHANGES.md | 1 +
 2 files changed, 2 insertions(+)

diff --git a/CHANGES.md b/CHANGES.md
index af37f3a337..59dad96973 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@ This document is intended for Spotless developers.
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
 
 ## [Unreleased]
+* Support for `gofmt` ([#861](https://github.com/diffplug/spotless/issues/861))
 
 ## [2.44.0] - 2024-01-15
 ### Added
diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index 77b39d6804..5d0d741931 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -3,6 +3,7 @@
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
 
 ## [Unreleased]
+* Support for `gofmt` ([#861](https://github.com/diffplug/spotless/issues/861))
 
 ## [6.24.0] - 2024-01-15
 ### Added

From 32f33f11b1f04dbcf74d04f723909a7590f02832 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Mon, 15 Jan 2024 22:35:04 +0100
Subject: [PATCH 04/11] Run `spotlessApply`

---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
index 2020bbafa7..9449709b02 100644
--- a/README.md
+++ b/README.md
@@ -132,6 +132,7 @@ lib('yaml.JacksonYamlStep')                      +'{{yes}}       | {{yes}}
 | [`biome.BiomeStep`](lib/src/main/java/com/diffplug/spotless/biome/BiomeStep.java) | :+1:       | :+1:      | :white_large_square:       | :white_large_square:  |
 | [`cpp.ClangFormatStep`](lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java) | :+1:       | :white_large_square:       | :white_large_square:       | :white_large_square:  |
 | [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1:       | :+1:      | :+1:      | :white_large_square:  |
+| [`go.GofmtFormatStep`](lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java) | :+1:       | :white_large_square:       | :white_large_square:       | :white_large_square:  |
 | [`gherkin.GherkinUtilsStep`](lib/src/main/java/com/diffplug/spotless/gherkin/GherkinUtilsStep.java) | :+1:       | :+1:      | :white_large_square:       | :white_large_square:  |
 | [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1:       | :+1:      | :+1:      | :white_large_square:  |
 | [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1:       | :+1:      | :+1:      | :white_large_square:  |

From 6b2a8e0ce1de4ddc1a788e5cd7ff1f726023fc57 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Mon, 15 Jan 2024 23:03:29 +0100
Subject: [PATCH 05/11] Fix spotbugs findings

---
 .../main/java/com/diffplug/spotless/go/GofmtFormatStep.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
index 82cc4956de..9b5dac5f48 100644
--- a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
@@ -94,7 +94,11 @@ public State(GofmtFormatStep step, ForeignExe goExecutable) {
 		String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
 			final List processArgs = new ArrayList<>();
 			String pathToGoBinary = exe.confirmVersionAndGetAbsolutePath();
-			String pathToGoFmt = Path.of(pathToGoBinary).getParent().resolve("gofmt").toString();
+			Path goBasePath = Path.of(pathToGoBinary).getParent();
+			if (goBasePath == null) {
+				throw new IllegalStateException("Unable to resolve base path of Go installation directory");
+			}
+			String pathToGoFmt = goBasePath.resolve("gofmt").toString();
 			processArgs.add(pathToGoFmt);
 			return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8);
 		}

From 4aac2f52b2b1cecd2eb45300d05c5256002c0a0c Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Tue, 16 Jan 2024 17:42:47 +0100
Subject: [PATCH 06/11] Apply review suggestions

---
 CHANGES.md               | 2 +-
 plugin-gradle/CHANGES.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 59dad96973..d6dc48b10f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,7 +10,7 @@ This document is intended for Spotless developers.
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
 
 ## [Unreleased]
-* Support for `gofmt` ([#861](https://github.com/diffplug/spotless/issues/861))
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
 
 ## [2.44.0] - 2024-01-15
 ### Added
diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index 5d0d741931..b3d918e343 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -3,7 +3,7 @@
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
 
 ## [Unreleased]
-* Support for `gofmt` ([#861](https://github.com/diffplug/spotless/issues/861))
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
 
 ## [6.24.0] - 2024-01-15
 ### Added

From e868f630283b19a7166f7c91d227349600b90541 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Tue, 16 Jan 2024 18:08:27 +0100
Subject: [PATCH 07/11] Implement gofmt support in plugin-maven

---
 plugin-maven/CHANGES.md                       |  1 +
 plugin-maven/README.md                        | 28 +++++++++++++++++++
 .../spotless/maven/AbstractSpotlessMojo.java  |  6 +++-
 .../com/diffplug/spotless/maven/go/Go.java    | 23 +++++++++++++++
 .../com/diffplug/spotless/maven/go/Gofmt.java | 25 +++++++++++++++++
 .../maven/MavenIntegrationHarness.java        |  4 +++
 .../diffplug/spotless/maven/go/GofmtTest.java | 16 +++++++++++
 7 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
 create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
 create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java

diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md
index 789f4430f4..4966621d38 100644
--- a/plugin-maven/CHANGES.md
+++ b/plugin-maven/CHANGES.md
@@ -3,6 +3,7 @@
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
 
 ## [Unreleased]
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
 
 ## [2.42.0] - 2024-01-15
 ### Added
diff --git a/plugin-maven/README.md b/plugin-maven/README.md
index efc15b515f..47ee6b5d37 100644
--- a/plugin-maven/README.md
+++ b/plugin-maven/README.md
@@ -54,6 +54,7 @@ user@machine repo % mvn spotless:check
   - [JSON](#json) ([simple](#simple), [gson](#gson), [jackson](#jackson), [Biome](#biome), [jsonPatch](#jsonPatch))
   - [YAML](#yaml)
   - [Gherkin](#gherkin)
+  - [Go](#go)
   - Multiple languages
     - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection), [caching `npm install` results](#caching-results-of-npm-install))
     - [eclipse web tools platform](#eclipse-web-tools-platform)
@@ -1047,6 +1048,33 @@ Uses a Gherkin pretty-printer that optionally allows configuring the number of s
 
 ```
 
+## Go
+
+- `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java)
+
+```xml
+
+  
+         
+      src/**/*.go
+    
+
+        
+  
+
+```
+
+### gofmt
+
+Standard Go formatter, part of Go distribution.
+
+```xml
+
+  go1.25.1
+  /opt/sdks/go1.25.1/bin/go
+
+```
+
 ## Prettier
 
 [homepage](https://prettier.io/). [changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md). [official plugins](https://prettier.io/docs/en/plugins.html#official-plugins). [community plugins](https://prettier.io/docs/en/plugins.html#community-plugins). Prettier is a formatter that can format almost every anything - JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown (including GFM and MDX), and YAML.  It can format even more [using plugins](https://prettier.io/docs/en/plugins.html) (PHP, Ruby, Swift, XML, Apex, Elm, Java (!!), Kotlin, pgSQL, .properties, solidity, svelte, toml, shellscript, ...).
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
index 97a61ddaea..2cecfaa1c1 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
@@ -38,6 +38,7 @@
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
+import com.diffplug.spotless.maven.go.Go;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Component;
@@ -184,6 +185,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
 	@Parameter
 	private Gherkin gherkin;
 
+	@Parameter
+	private Go go;
+
 	@Parameter(property = "spotlessFiles")
 	private String filePatterns;
 
@@ -358,7 +362,7 @@ private FileLocator getFileLocator() {
 	}
 
 	private List getFormatterFactories() {
-		return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, javascript, antlr4, pom, sql, python, markdown, json, yaml, gherkin))
+		return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, javascript, antlr4, pom, sql, python, markdown, json, yaml, gherkin, go))
 				.filter(Objects::nonNull)
 				.collect(toList());
 	}
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
new file mode 100644
index 0000000000..b69f6652cb
--- /dev/null
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
@@ -0,0 +1,23 @@
+package com.diffplug.spotless.maven.go;
+
+import com.diffplug.spotless.maven.FormatterFactory;
+import org.apache.maven.project.MavenProject;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class Go extends FormatterFactory {
+    @Override
+    public Set defaultIncludes(MavenProject project) {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public String licenseHeaderDelimiter() {
+        return null;
+    }
+
+    public void addGofmt(Gofmt gofmt) {
+        addStepFactory(gofmt);
+    }
+}
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
new file mode 100644
index 0000000000..47bb9576c8
--- /dev/null
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
@@ -0,0 +1,25 @@
+package com.diffplug.spotless.maven.go;
+
+import com.diffplug.spotless.FormatterStep;
+import com.diffplug.spotless.go.GofmtFormatStep;
+import com.diffplug.spotless.maven.FormatterStepConfig;
+import com.diffplug.spotless.maven.FormatterStepFactory;
+import org.apache.maven.plugins.annotations.Parameter;
+
+public class Gofmt implements FormatterStepFactory {
+
+    @Parameter
+    private String version;
+
+    @Parameter
+    private String goExecutablePath;
+
+    @Override
+    public FormatterStep newFormatterStep(FormatterStepConfig config) {
+        GofmtFormatStep step = GofmtFormatStep.withVersion(version == null ? GofmtFormatStep.defaultVersion() : version);
+        if (goExecutablePath != null) {
+            step = step.withGoExecutable(goExecutablePath);
+        }
+        return step.create();
+    }
+}
diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
index 4710874e9f..e9b0233a14 100644
--- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
@@ -187,6 +187,10 @@ protected void writePomWithGherkinSteps(String... steps) throws IOException {
 		writePom(groupWithSteps("gherkin", including("**/*.feature"), steps));
 	}
 
+	protected void writePomWithGoSteps(String... steps) throws IOException {
+		writePom(groupWithSteps("go", including("**/*.go"), steps));
+	}
+
 	protected void writePom(String... configuration) throws IOException {
 		writePom(null, configuration, null, null);
 	}
diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java
new file mode 100644
index 0000000000..a8ba456325
--- /dev/null
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java
@@ -0,0 +1,16 @@
+package com.diffplug.spotless.maven.go;
+
+import com.diffplug.spotless.maven.MavenIntegrationHarness;
+import org.junit.jupiter.api.Test;
+
+@com.diffplug.spotless.tag.GofmtTest
+public class GofmtTest extends MavenIntegrationHarness {
+    @Test
+    void testGofmt() throws Exception {
+        writePomWithGoSteps("go1.21.5");
+
+        setFile("src/main/go/example.go").toResource("go/gofmt/go.dirty");
+        mavenRunner().withArguments("spotless:apply").runNoError();
+        assertFile("src/main/go/example.go").sameAsResource("go/gofmt/go.clean");
+    }
+}

From 2870d069634c5f35f920a560caf96adbda466b74 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Tue, 16 Jan 2024 18:14:55 +0100
Subject: [PATCH 08/11] Run `spotlessApply`

---
 .../spotless/maven/AbstractSpotlessMojo.java  |  4 +-
 .../com/diffplug/spotless/maven/go/Go.java    | 44 +++++++++++++------
 .../com/diffplug/spotless/maven/go/Gofmt.java | 42 ++++++++++++------
 .../maven/MavenIntegrationHarness.java        |  2 +-
 .../diffplug/spotless/maven/go/GofmtTest.java | 32 ++++++++++----
 5 files changed, 86 insertions(+), 38 deletions(-)

diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
index 2cecfaa1c1..35e490b581 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 DiffPlug
+ * Copyright 2016-2024 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
-import com.diffplug.spotless.maven.go.Go;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Component;
@@ -63,6 +62,7 @@
 import com.diffplug.spotless.maven.generic.Format;
 import com.diffplug.spotless.maven.generic.LicenseHeader;
 import com.diffplug.spotless.maven.gherkin.Gherkin;
+import com.diffplug.spotless.maven.go.Go;
 import com.diffplug.spotless.maven.groovy.Groovy;
 import com.diffplug.spotless.maven.incremental.UpToDateChecker;
 import com.diffplug.spotless.maven.incremental.UpToDateChecking;
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
index b69f6652cb..bb26bd0355 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java
@@ -1,23 +1,39 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.diffplug.spotless.maven.go;
 
-import com.diffplug.spotless.maven.FormatterFactory;
-import org.apache.maven.project.MavenProject;
-
 import java.util.Collections;
 import java.util.Set;
 
+import org.apache.maven.project.MavenProject;
+
+import com.diffplug.spotless.maven.FormatterFactory;
+
 public class Go extends FormatterFactory {
-    @Override
-    public Set defaultIncludes(MavenProject project) {
-        return Collections.emptySet();
-    }
+	@Override
+	public Set defaultIncludes(MavenProject project) {
+		return Collections.emptySet();
+	}
 
-    @Override
-    public String licenseHeaderDelimiter() {
-        return null;
-    }
+	@Override
+	public String licenseHeaderDelimiter() {
+		return null;
+	}
 
-    public void addGofmt(Gofmt gofmt) {
-        addStepFactory(gofmt);
-    }
+	public void addGofmt(Gofmt gofmt) {
+		addStepFactory(gofmt);
+	}
 }
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
index 47bb9576c8..aaa30efb4f 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Gofmt.java
@@ -1,25 +1,41 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.diffplug.spotless.maven.go;
 
+import org.apache.maven.plugins.annotations.Parameter;
+
 import com.diffplug.spotless.FormatterStep;
 import com.diffplug.spotless.go.GofmtFormatStep;
 import com.diffplug.spotless.maven.FormatterStepConfig;
 import com.diffplug.spotless.maven.FormatterStepFactory;
-import org.apache.maven.plugins.annotations.Parameter;
 
 public class Gofmt implements FormatterStepFactory {
 
-    @Parameter
-    private String version;
+	@Parameter
+	private String version;
 
-    @Parameter
-    private String goExecutablePath;
+	@Parameter
+	private String goExecutablePath;
 
-    @Override
-    public FormatterStep newFormatterStep(FormatterStepConfig config) {
-        GofmtFormatStep step = GofmtFormatStep.withVersion(version == null ? GofmtFormatStep.defaultVersion() : version);
-        if (goExecutablePath != null) {
-            step = step.withGoExecutable(goExecutablePath);
-        }
-        return step.create();
-    }
+	@Override
+	public FormatterStep newFormatterStep(FormatterStepConfig config) {
+		GofmtFormatStep step = GofmtFormatStep.withVersion(version == null ? GofmtFormatStep.defaultVersion() : version);
+		if (goExecutablePath != null) {
+			step = step.withGoExecutable(goExecutablePath);
+		}
+		return step.create();
+	}
 }
diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
index e9b0233a14..45256de6c3 100644
--- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 DiffPlug
+ * Copyright 2016-2024 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java
index a8ba456325..5cf4398f70 100644
--- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/go/GofmtTest.java
@@ -1,16 +1,32 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.diffplug.spotless.maven.go;
 
-import com.diffplug.spotless.maven.MavenIntegrationHarness;
 import org.junit.jupiter.api.Test;
 
+import com.diffplug.spotless.maven.MavenIntegrationHarness;
+
 @com.diffplug.spotless.tag.GofmtTest
 public class GofmtTest extends MavenIntegrationHarness {
-    @Test
-    void testGofmt() throws Exception {
-        writePomWithGoSteps("go1.21.5");
+	@Test
+	void testGofmt() throws Exception {
+		writePomWithGoSteps("go1.21.5");
 
-        setFile("src/main/go/example.go").toResource("go/gofmt/go.dirty");
-        mavenRunner().withArguments("spotless:apply").runNoError();
-        assertFile("src/main/go/example.go").sameAsResource("go/gofmt/go.clean");
-    }
+		setFile("src/main/go/example.go").toResource("go/gofmt/go.dirty");
+		mavenRunner().withArguments("spotless:apply").runNoError();
+		assertFile("src/main/go/example.go").sameAsResource("go/gofmt/go.clean");
+	}
 }

From d3f7680bf7c5e7d4bfa821e5a1e50533edf8defe Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Wed, 17 Jan 2024 18:49:25 +0100
Subject: [PATCH 09/11] Introduce `go` extension for plugin-gradle

---
 .../diffplug/spotless/go/GofmtFormatStep.java |  2 +-
 .../gradle/spotless/FormatExtension.java      | 27 ---------
 .../diffplug/gradle/spotless/GoExtension.java | 57 +++++++++++++++++++
 .../gradle/spotless/SpotlessExtension.java    |  5 ++
 .../gradle/spotless/GoGradleTest.java         |  4 +-
 5 files changed, 65 insertions(+), 30 deletions(-)
 create mode 100644 plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java

diff --git a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
index 9b5dac5f48..18e388cf5b 100644
--- a/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
@@ -43,7 +43,7 @@ public static String name() {
 	}
 
 	public static String defaultVersion() {
-		return "1.20.0";
+		return "go1.20.0";
 	}
 
 	private final String version;
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index a19918796e..73189ba4e0 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -957,33 +957,6 @@ public EclipseWtpConfig eclipseWtp(EclipseWtpFormatterStep type, String version)
 		return new EclipseWtpConfig(type, version);
 	}
 
-	public class GofmtConfig {
-		GofmtFormatStep stepCfg;
-
-		public GofmtConfig(String version) {
-			stepCfg = (GofmtFormatStep) GofmtFormatStep.withVersion(version).create();
-			addStep(createStep());
-		}
-
-		public GofmtConfig withGoExecutable(String pathToGo) {
-			stepCfg = stepCfg.withGoExecutable(pathToGo);
-			replaceStep(createStep());
-			return this;
-		}
-
-		private FormatterStep createStep() {
-			return stepCfg.create();
-		}
-	}
-
-	public GofmtConfig gofmt() {
-		return new GofmtConfig(GofmtFormatStep.defaultVersion());
-	}
-
-	public GofmtConfig gofmt(String version) {
-		return new GofmtConfig(version);
-	}
-
 	/**
 	 * 
 	 * spotless {
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java
new file mode 100644
index 0000000000..60aa1aa71d
--- /dev/null
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2024 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.gradle.spotless;
+
+import com.diffplug.spotless.FormatterStep;
+import com.diffplug.spotless.go.GofmtFormatStep;
+
+import javax.inject.Inject;
+
+public class GoExtension extends FormatExtension {
+    public static final String NAME = "go";
+
+    @Inject
+    public GoExtension(SpotlessExtension spotless) {
+        super(spotless);
+    }
+
+    public GofmtConfig gofmt() {
+        return new GofmtConfig(GofmtFormatStep.defaultVersion());
+    }
+
+    public GofmtConfig gofmt(String version) {
+        return new GofmtConfig(version);
+    }
+
+    public class GofmtConfig {
+        GofmtFormatStep stepCfg;
+
+        public GofmtConfig(String version) {
+            stepCfg = GofmtFormatStep.withVersion(version);
+            addStep(createStep());
+        }
+
+        public GofmtConfig withGoExecutable(String pathToGo) {
+            stepCfg = stepCfg.withGoExecutable(pathToGo);
+            replaceStep(createStep());
+            return this;
+        }
+
+        private FormatterStep createStep() {
+            return stepCfg.create();
+        }
+    }
+}
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
index b4c8e3cc03..f02ac28548 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
@@ -223,6 +223,11 @@ public void gherkin(Action closure) {
 		format(GherkinExtension.NAME, GherkinExtension.class, closure);
 	}
 
+	public void go(Action closure) {
+		requireNonNull(closure);
+		format(GoExtension.NAME, GoExtension.class, closure);
+	}
+
 	/** Configures a custom extension. */
 	public void format(String name, Action closure) {
 		requireNonNull(name, "name");
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
index 1d5fea7e41..94bd345854 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoGradleTest.java
@@ -30,9 +30,9 @@ void gofmt() throws IOException {
 				"  id 'com.diffplug.spotless'",
 				"}",
 				"spotless {",
-				"  format 'go' {",
+				"  go {",
 				"    target 'src/**/*.go'",
-				"    gofmt()",
+				"    gofmt(\"go1.21.5\")",
 				"  }",
 				"}");
 		setFile("src/test.go").toResource("go/gofmt/go.dirty");

From 163ed2d7987cd6a819cf5f930ba51a9f978c4093 Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Wed, 17 Jan 2024 18:56:19 +0100
Subject: [PATCH 10/11] Run `spotlessApply`

---
 .../gradle/spotless/FormatExtension.java      |  1 -
 .../diffplug/gradle/spotless/GoExtension.java | 70 +++++++++----------
 2 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index 73189ba4e0..6f6630b1b5 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -65,7 +65,6 @@
 import com.diffplug.spotless.generic.ReplaceRegexStep;
 import com.diffplug.spotless.generic.ReplaceStep;
 import com.diffplug.spotless.generic.TrimTrailingWhitespaceStep;
-import com.diffplug.spotless.go.GofmtFormatStep;
 import com.diffplug.spotless.npm.NpmPathResolver;
 import com.diffplug.spotless.npm.PrettierFormatterStep;
 import com.diffplug.spotless.rome.BiomeFlavor;
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java
index 60aa1aa71d..145e90c19a 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GoExtension.java
@@ -15,43 +15,43 @@
  */
 package com.diffplug.gradle.spotless;
 
+import javax.inject.Inject;
+
 import com.diffplug.spotless.FormatterStep;
 import com.diffplug.spotless.go.GofmtFormatStep;
 
-import javax.inject.Inject;
-
 public class GoExtension extends FormatExtension {
-    public static final String NAME = "go";
-
-    @Inject
-    public GoExtension(SpotlessExtension spotless) {
-        super(spotless);
-    }
-
-    public GofmtConfig gofmt() {
-        return new GofmtConfig(GofmtFormatStep.defaultVersion());
-    }
-
-    public GofmtConfig gofmt(String version) {
-        return new GofmtConfig(version);
-    }
-
-    public class GofmtConfig {
-        GofmtFormatStep stepCfg;
-
-        public GofmtConfig(String version) {
-            stepCfg = GofmtFormatStep.withVersion(version);
-            addStep(createStep());
-        }
-
-        public GofmtConfig withGoExecutable(String pathToGo) {
-            stepCfg = stepCfg.withGoExecutable(pathToGo);
-            replaceStep(createStep());
-            return this;
-        }
-
-        private FormatterStep createStep() {
-            return stepCfg.create();
-        }
-    }
+	public static final String NAME = "go";
+
+	@Inject
+	public GoExtension(SpotlessExtension spotless) {
+		super(spotless);
+	}
+
+	public GofmtConfig gofmt() {
+		return new GofmtConfig(GofmtFormatStep.defaultVersion());
+	}
+
+	public GofmtConfig gofmt(String version) {
+		return new GofmtConfig(version);
+	}
+
+	public class GofmtConfig {
+		GofmtFormatStep stepCfg;
+
+		public GofmtConfig(String version) {
+			stepCfg = GofmtFormatStep.withVersion(version);
+			addStep(createStep());
+		}
+
+		public GofmtConfig withGoExecutable(String pathToGo) {
+			stepCfg = stepCfg.withGoExecutable(pathToGo);
+			replaceStep(createStep());
+			return this;
+		}
+
+		private FormatterStep createStep() {
+			return stepCfg.create();
+		}
+	}
 }

From 9d71e6d7c3a00437a1e838d1949066d2ebce367b Mon Sep 17 00:00:00 2001
From: Peter Trifanov 
Date: Sat, 20 Jan 2024 17:30:49 +0100
Subject: [PATCH 11/11] Fixes according to review

---
 CHANGES.md                                                      | 2 +-
 plugin-gradle/CHANGES.md                                        | 2 +-
 .../main/java/com/diffplug/gradle/spotless/FormatExtension.java | 2 +-
 plugin-maven/CHANGES.md                                         | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 272735a791..e13eed2745 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,7 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
 ## [Unreleased]
 ### Added
 * Maven - Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/pull/1998))
-* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
 
 ## [2.44.0] - 2024-01-15
 ### Added
diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index 4a0ac12a5b..b712a4e3d8 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -3,7 +3,7 @@
 We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
 
 ## [Unreleased]
-* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
 
 ## [6.24.0] - 2024-01-15
 ### Added
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index 6f6630b1b5..eae8ac667d 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2024 DiffPlug
+ * Copyright 2016-2023 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md
index e73ccde66d..b7dd430f8e 100644
--- a/plugin-maven/CHANGES.md
+++ b/plugin-maven/CHANGES.md
@@ -5,7 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
 ## [Unreleased]
 ### Added
 * Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/issues/1998))
-* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/issues/2001))
+* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
 
 ## [2.42.0] - 2024-01-15
 ### Added