Skip to content

Commit 706f18e

Browse files
authored
Add support for gofmt (#2001)
2 parents 13d9627 + a145ac0 commit 706f18e

File tree

19 files changed

+463
-4
lines changed

19 files changed

+463
-4
lines changed

CHANGES.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1111

1212
## [Unreleased]
1313
### Added
14-
* Maven - Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/pull/1998))
15-
* Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
14+
* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
15+
* Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
1616

1717
## [2.44.0] - 2024-01-15
1818
### Added

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ lib('antlr4.Antlr4FormatterStep') +'{{yes}} | {{yes}}
7878
lib('biome.BiomeStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
7979
lib('cpp.ClangFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
8080
extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
81+
lib('go.GofmtFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
8182
lib('gherkin.GherkinUtilsStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
8283
extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
8384
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
@@ -131,6 +132,7 @@ lib('yaml.JacksonYamlStep') +'{{yes}} | {{yes}}
131132
| [`biome.BiomeStep`](lib/src/main/java/com/diffplug/spotless/biome/BiomeStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
132133
| [`cpp.ClangFormatStep`](lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
133134
| [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
135+
| [`go.GofmtFormatStep`](lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
134136
| [`gherkin.GherkinUtilsStep`](lib/src/main/java/com/diffplug/spotless/gherkin/GherkinUtilsStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
135137
| [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
136138
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :+1: | :white_large_square: |

gradle/special-tests.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def special = [
55
'Black',
66
'Buf',
77
'Clang',
8+
'gofmt',
89
'Npm',
910
'Shfmt'
1011
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.go;
17+
18+
import java.io.File;
19+
import java.io.IOException;
20+
import java.io.Serializable;
21+
import java.nio.charset.StandardCharsets;
22+
import java.nio.file.Path;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.Objects;
26+
27+
import javax.annotation.Nullable;
28+
29+
import com.diffplug.spotless.ForeignExe;
30+
import com.diffplug.spotless.FormatterFunc;
31+
import com.diffplug.spotless.FormatterStep;
32+
import com.diffplug.spotless.ProcessRunner;
33+
34+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
35+
36+
/**
37+
* Note: gofmt doesn't have a version flag, because it's part of standard Go distribution.
38+
* So `go` executable can be used to determine base path and version, and path to gofmt can be built from it.
39+
*/
40+
public class GofmtFormatStep {
41+
public static String name() {
42+
return "gofmt";
43+
}
44+
45+
public static String defaultVersion() {
46+
return "go1.20.0";
47+
}
48+
49+
private final String version;
50+
private final @Nullable String pathToExe;
51+
52+
private GofmtFormatStep(String version, String pathToExe) {
53+
this.version = version;
54+
this.pathToExe = pathToExe;
55+
}
56+
57+
public static GofmtFormatStep withVersion(String version) {
58+
return new GofmtFormatStep(version, null);
59+
}
60+
61+
public GofmtFormatStep withGoExecutable(String pathToExe) {
62+
return new GofmtFormatStep(version, pathToExe);
63+
}
64+
65+
public FormatterStep create() {
66+
return FormatterStep.createLazy(name(), this::createState, GofmtFormatStep.State::toFunc);
67+
}
68+
69+
private State createState() throws IOException, InterruptedException {
70+
String howToInstall = "gofmt is a part of standard go distribution. If spotless can't discover it automatically, " +
71+
"you can point Spotless to the go binary with {@code pathToExe('/path/to/go')}";
72+
final ForeignExe exe = ForeignExe.nameAndVersion("go", version)
73+
.pathToExe(pathToExe)
74+
.versionFlag("version")
75+
.fixCantFind(howToInstall)
76+
.fixWrongVersion(
77+
"You can tell Spotless to use the version you already have with {@code gofmt('{versionFound}')}" +
78+
"or you can install the currently specified Go version, {version}.\n" + howToInstall);
79+
return new State(this, exe);
80+
}
81+
82+
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
83+
static class State implements Serializable {
84+
private static final long serialVersionUID = -1825662355363926318L;
85+
// used for up-to-date checks and caching
86+
final String version;
87+
final transient ForeignExe exe;
88+
89+
public State(GofmtFormatStep step, ForeignExe goExecutable) {
90+
this.version = step.version;
91+
this.exe = Objects.requireNonNull(goExecutable);
92+
}
93+
94+
String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
95+
final List<String> processArgs = new ArrayList<>();
96+
String pathToGoBinary = exe.confirmVersionAndGetAbsolutePath();
97+
Path goBasePath = Path.of(pathToGoBinary).getParent();
98+
if (goBasePath == null) {
99+
throw new IllegalStateException("Unable to resolve base path of Go installation directory");
100+
}
101+
String pathToGoFmt = goBasePath.resolve("gofmt").toString();
102+
processArgs.add(pathToGoFmt);
103+
return runner.exec(input.getBytes(StandardCharsets.UTF_8), processArgs).assertExitZero(StandardCharsets.UTF_8);
104+
}
105+
106+
FormatterFunc.Closeable toFunc() {
107+
ProcessRunner runner = new ProcessRunner();
108+
return FormatterFunc.Closeable.of(runner, this::format);
109+
}
110+
}
111+
}

plugin-gradle/CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
44

55
## [Unreleased]
6+
* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
67

78
### Added
89
* Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.gradle.spotless;
17+
18+
import javax.inject.Inject;
19+
20+
import com.diffplug.spotless.FormatterStep;
21+
import com.diffplug.spotless.go.GofmtFormatStep;
22+
23+
public class GoExtension extends FormatExtension {
24+
public static final String NAME = "go";
25+
26+
@Inject
27+
public GoExtension(SpotlessExtension spotless) {
28+
super(spotless);
29+
}
30+
31+
public GofmtConfig gofmt() {
32+
return new GofmtConfig(GofmtFormatStep.defaultVersion());
33+
}
34+
35+
public GofmtConfig gofmt(String version) {
36+
return new GofmtConfig(version);
37+
}
38+
39+
public class GofmtConfig {
40+
GofmtFormatStep stepCfg;
41+
42+
public GofmtConfig(String version) {
43+
stepCfg = GofmtFormatStep.withVersion(version);
44+
addStep(createStep());
45+
}
46+
47+
public GofmtConfig withGoExecutable(String pathToGo) {
48+
stepCfg = stepCfg.withGoExecutable(pathToGo);
49+
replaceStep(createStep());
50+
return this;
51+
}
52+
53+
private FormatterStep createStep() {
54+
return stepCfg.create();
55+
}
56+
}
57+
}

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java

+5
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ public void gherkin(Action<GherkinExtension> closure) {
223223
format(GherkinExtension.NAME, GherkinExtension.class, closure);
224224
}
225225

226+
public void go(Action<GoExtension> closure) {
227+
requireNonNull(closure);
228+
format(GoExtension.NAME, GoExtension.class, closure);
229+
}
230+
226231
/** Configures a custom extension. */
227232
public void format(String name, Action<FormatExtension> closure) {
228233
requireNonNull(name, "name");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2020-2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.gradle.spotless;
17+
18+
import java.io.IOException;
19+
20+
import org.junit.jupiter.api.Test;
21+
22+
import com.diffplug.spotless.tag.GofmtTest;
23+
24+
@GofmtTest
25+
class GoGradleTest extends GradleIntegrationHarness {
26+
@Test
27+
void gofmt() throws IOException {
28+
setFile("build.gradle").toLines(
29+
"plugins {",
30+
" id 'com.diffplug.spotless'",
31+
"}",
32+
"spotless {",
33+
" go {",
34+
" target 'src/**/*.go'",
35+
" gofmt(\"go1.21.5\")",
36+
" }",
37+
"}");
38+
setFile("src/test.go").toResource("go/gofmt/go.dirty");
39+
gradleRunner().withArguments("spotlessApply").build();
40+
assertFile("src/test.go").sameAsResource("go/gofmt/go.clean");
41+
}
42+
}

plugin-maven/CHANGES.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
55
## [Unreleased]
66
### Added
77
* Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/issues/1998))
8-
* Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
8+
* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
9+
* Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
910

1011
## [2.42.0] - 2024-01-15
1112
### Added

plugin-maven/README.md

+28
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ user@machine repo % mvn spotless:check
5454
- [JSON](#json) ([simple](#simple), [gson](#gson), [jackson](#jackson), [Biome](#biome), [jsonPatch](#jsonPatch))
5555
- [YAML](#yaml)
5656
- [Gherkin](#gherkin)
57+
- [Go](#go)
5758
- Multiple languages
5859
- [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection), [caching `npm install` results](#caching-results-of-npm-install))
5960
- [eclipse web tools platform](#eclipse-web-tools-platform)
@@ -1048,6 +1049,33 @@ Uses a Gherkin pretty-printer that optionally allows configuring the number of s
10481049
</gherkinUtils>
10491050
```
10501051

1052+
## Go
1053+
1054+
- `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)
1055+
1056+
```xml
1057+
<configuration>
1058+
<go>
1059+
<includes> <!-- You have to set the target manually -->
1060+
<include>src/**/*.go</include>
1061+
</includes>
1062+
1063+
<gofmt /> <!-- has its own section below -->
1064+
</go>
1065+
</configuration>
1066+
```
1067+
1068+
### gofmt
1069+
1070+
Standard Go formatter, part of Go distribution.
1071+
1072+
```xml
1073+
<gofmt>
1074+
<version>go1.25.1</version>
1075+
<goExecutablePath>/opt/sdks/go1.25.1/bin/go</goExecutablePath>
1076+
</gofmt>
1077+
```
1078+
10511079
## Prettier
10521080

10531081
[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, ...).

plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import com.diffplug.spotless.maven.generic.Format;
6363
import com.diffplug.spotless.maven.generic.LicenseHeader;
6464
import com.diffplug.spotless.maven.gherkin.Gherkin;
65+
import com.diffplug.spotless.maven.go.Go;
6566
import com.diffplug.spotless.maven.groovy.Groovy;
6667
import com.diffplug.spotless.maven.incremental.UpToDateChecker;
6768
import com.diffplug.spotless.maven.incremental.UpToDateChecking;
@@ -188,6 +189,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
188189
@Parameter
189190
private Gherkin gherkin;
190191

192+
@Parameter
193+
private Go go;
194+
191195
@Parameter(property = "spotlessFiles")
192196
private String filePatterns;
193197

@@ -362,7 +366,7 @@ private FileLocator getFileLocator() {
362366
}
363367

364368
private List<FormatterFactory> getFormatterFactories() {
365-
return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, javascript, antlr4, pom, sql, python, markdown, json, shell, yaml, gherkin))
369+
return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, javascript, antlr4, pom, sql, python, markdown, json, shell, yaml, gherkin, go))
366370
.filter(Objects::nonNull)
367371
.collect(toList());
368372
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2024 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.maven.go;
17+
18+
import java.util.Collections;
19+
import java.util.Set;
20+
21+
import org.apache.maven.project.MavenProject;
22+
23+
import com.diffplug.spotless.maven.FormatterFactory;
24+
25+
public class Go extends FormatterFactory {
26+
@Override
27+
public Set<String> defaultIncludes(MavenProject project) {
28+
return Collections.emptySet();
29+
}
30+
31+
@Override
32+
public String licenseHeaderDelimiter() {
33+
return null;
34+
}
35+
36+
public void addGofmt(Gofmt gofmt) {
37+
addStepFactory(gofmt);
38+
}
39+
}

0 commit comments

Comments
 (0)