Skip to content

Commit 19b25be

Browse files
authoredMar 27, 2023
Convert GJF to compile only dependency, bump min to 1.8, bump default to 1.16.0 (#1630)
2 parents ccf0eb4 + 3aea790 commit 19b25be

25 files changed

+263
-245
lines changed
 

‎CHANGES.md

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Changes
14+
* **POTENTIALLY BREAKING** Converted `googleJavaFormat` to a compile-only dependency and drop support for versions < `1.8`. ([#1630](https://github.com/diffplug/spotless/pull/1630))
15+
* Bump default `googleJavaFormat` version `1.15.0` -> `1.16.0`. ([#1630](https://github.com/diffplug/spotless/pull/1630))
1316

1417
## [2.37.0] - 2023-03-13
1518
### Added

‎lib/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ apply from: rootProject.file('gradle/java-publish.gradle')
1010
def NEEDS_GLUE = [
1111
'sortPom',
1212
'palantirJavaFormat',
13+
'googleJavaFormat',
1314
'ktfmt',
1415
'ktlint',
1516
'flexmark',
@@ -70,6 +71,8 @@ dependencies {
7071

7172
palantirJavaFormatCompileOnly 'com.palantir.javaformat:palantir-java-format:1.1.0' // this version needs to stay compilable against Java 8 for CI Job testNpm
7273

74+
googleJavaFormatCompileOnly 'com.google.googlejavaformat:google-java-format:1.8' // minimum required version due to api changes before then
75+
7376
// used jackson-based formatters
7477
jacksonCompileOnly 'com.fasterxml.jackson.core:jackson-databind:2.14.2'
7578
jacksonCompileOnly 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.2'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2023 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.glue.java;
17+
18+
import java.util.Objects;
19+
20+
import javax.annotation.Nonnull;
21+
22+
import com.google.googlejavaformat.java.Formatter;
23+
import com.google.googlejavaformat.java.FormatterException;
24+
import com.google.googlejavaformat.java.ImportOrderer;
25+
import com.google.googlejavaformat.java.JavaFormatterOptions;
26+
import com.google.googlejavaformat.java.RemoveUnusedImports;
27+
import com.google.googlejavaformat.java.StringWrapper;
28+
29+
import com.diffplug.spotless.FormatterFunc;
30+
31+
public class GoogleJavaFormatFormatterFunc implements FormatterFunc {
32+
33+
@Nonnull
34+
private final Formatter formatter;
35+
36+
@Nonnull
37+
private final String version;
38+
39+
@Nonnull
40+
private final JavaFormatterOptions.Style formatterStyle;
41+
42+
private final boolean reflowStrings;
43+
44+
public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String style, boolean reflowStrings) {
45+
this.version = Objects.requireNonNull(version);
46+
this.formatterStyle = JavaFormatterOptions.Style.valueOf(Objects.requireNonNull(style));
47+
this.reflowStrings = reflowStrings;
48+
49+
this.formatter = new Formatter(JavaFormatterOptions.builder()
50+
.style(formatterStyle)
51+
.build());
52+
}
53+
54+
@Override
55+
@Nonnull
56+
public String apply(@Nonnull String input) throws Exception {
57+
String formatted = formatter.formatSource(input);
58+
String removedUnused = RemoveUnusedImports.removeUnusedImports(formatted);
59+
String sortedImports = ImportOrderer.reorderImports(removedUnused, formatterStyle);
60+
return reflowLongStrings(sortedImports);
61+
}
62+
63+
private String reflowLongStrings(String input) throws FormatterException {
64+
if (reflowStrings) {
65+
return StringWrapper.wrap(input, formatter);
66+
} else {
67+
return input;
68+
}
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2023 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.glue.java;
17+
18+
import java.util.Objects;
19+
20+
import javax.annotation.Nonnull;
21+
22+
import com.google.googlejavaformat.java.RemoveUnusedImports;
23+
24+
import com.diffplug.spotless.FormatterFunc;
25+
26+
public class GoogleJavaFormatRemoveUnusedImporterFormatterFunc implements FormatterFunc {
27+
28+
@Nonnull
29+
private final String version;
30+
31+
public GoogleJavaFormatRemoveUnusedImporterFormatterFunc(@Nonnull String version) {
32+
this.version = Objects.requireNonNull(version);
33+
}
34+
35+
@Override
36+
@Nonnull
37+
public String apply(@Nonnull String input) throws Exception {
38+
return RemoveUnusedImports.removeUnusedImports(input);
39+
}
40+
}

‎lib/src/main/java/com/diffplug/spotless/Jvm.java

+63-26
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ public static int version() {
6363
public static class Support<V> {
6464
private final String fmtName;
6565
private final Comparator<? super V> fmtVersionComparator;
66-
private final NavigableMap<Integer, V> jvm2fmtVersion;
67-
private final NavigableMap<V, Integer> fmt2jvmVersion;
66+
private final NavigableMap<Integer, V> jvm2fmtMaxVersion;
67+
private final NavigableMap<Integer, V> jvm2fmtMinVersion;
68+
private final NavigableMap<V, Integer> fmtMaxVersion2jvmVersion;
6869

6970
private Support(String fromatterName) {
7071
this(fromatterName, new SemanticVersionComparator<V>());
@@ -73,40 +74,60 @@ private Support(String fromatterName) {
7374
private Support(String formatterName, Comparator<? super V> formatterVersionComparator) {
7475
fmtName = formatterName;
7576
fmtVersionComparator = formatterVersionComparator;
76-
jvm2fmtVersion = new TreeMap<Integer, V>();
77-
fmt2jvmVersion = new TreeMap<V, Integer>(formatterVersionComparator);
77+
jvm2fmtMaxVersion = new TreeMap<>();
78+
jvm2fmtMinVersion = new TreeMap<>();
79+
fmtMaxVersion2jvmVersion = new TreeMap<>(formatterVersionComparator);
7880
}
7981

8082
/**
81-
* Add supported formatter version
83+
* Add maximum supported formatter version
8284
* @param minimumJvmVersion Minimum Java version required
8385
* @param maxFormatterVersion Maximum formatter version supported by the Java version
8486
* @return this
8587
*/
8688
public Support<V> add(int minimumJvmVersion, V maxFormatterVersion) {
8789
Objects.requireNonNull(maxFormatterVersion);
88-
if (null != jvm2fmtVersion.put(minimumJvmVersion, maxFormatterVersion)) {
90+
if (null != jvm2fmtMaxVersion.put(minimumJvmVersion, maxFormatterVersion)) {
8991
throw new IllegalArgumentException(String.format("Added duplicate entry for JVM %d+.", minimumJvmVersion));
9092
}
91-
if (null != fmt2jvmVersion.put(maxFormatterVersion, minimumJvmVersion)) {
93+
if (null != fmtMaxVersion2jvmVersion.put(maxFormatterVersion, minimumJvmVersion)) {
9294
throw new IllegalArgumentException(String.format("Added duplicate entry for formatter version %s.", maxFormatterVersion));
9395
}
96+
verifyVersionRangesDoNotIntersect(jvm2fmtMaxVersion, minimumJvmVersion, maxFormatterVersion);
97+
return this;
98+
}
99+
100+
public Support<V> addMin(int minimumJvmVersion, V minFormatterVersion) {
101+
Objects.requireNonNull(minFormatterVersion);
102+
if (null != jvm2fmtMinVersion.put(minimumJvmVersion, minFormatterVersion)) {
103+
throw new IllegalArgumentException(String.format("Added duplicate entry for JVM %d+.", minimumJvmVersion));
104+
}
105+
verifyVersionRangesDoNotIntersect(jvm2fmtMinVersion, minimumJvmVersion, minFormatterVersion);
106+
return this;
107+
}
108+
109+
private void verifyVersionRangesDoNotIntersect(NavigableMap<Integer, V> jvm2fmtVersion, int minimumJvmVersion, V formatterVersion) {
94110
Map.Entry<Integer, V> lower = jvm2fmtVersion.lowerEntry(minimumJvmVersion);
95-
if ((null != lower) && (fmtVersionComparator.compare(maxFormatterVersion, lower.getValue()) <= 0)) {
96-
throw new IllegalArgumentException(String.format("%d/%s should be lower than %d/%s", minimumJvmVersion, maxFormatterVersion, lower.getKey(), lower.getValue()));
111+
if ((null != lower) && (fmtVersionComparator.compare(formatterVersion, lower.getValue()) <= 0)) {
112+
throw new IllegalArgumentException(String.format("%d/%s should be lower than %d/%s", minimumJvmVersion, formatterVersion, lower.getKey(), lower.getValue()));
97113
}
98114
Map.Entry<Integer, V> higher = jvm2fmtVersion.higherEntry(minimumJvmVersion);
99-
if ((null != higher) && (fmtVersionComparator.compare(maxFormatterVersion, higher.getValue()) >= 0)) {
100-
throw new IllegalArgumentException(String.format("%d/%s should be higher than %d/%s", minimumJvmVersion, maxFormatterVersion, higher.getKey(), higher.getValue()));
115+
if ((null != higher) && (fmtVersionComparator.compare(formatterVersion, higher.getValue()) >= 0)) {
116+
throw new IllegalArgumentException(String.format("%d/%s should be higher than %d/%s", minimumJvmVersion, formatterVersion, higher.getKey(), higher.getValue()));
101117
}
102-
return this;
103118
}
104119

105120
/** @return Highest formatter version recommended for this JVM (null, if JVM not supported) */
106121
@Nullable
107122
public V getRecommendedFormatterVersion() {
108-
Integer configuredJvmVersionOrNull = jvm2fmtVersion.floorKey(Jvm.version());
109-
return (null == configuredJvmVersionOrNull) ? null : jvm2fmtVersion.get(configuredJvmVersionOrNull);
123+
Integer configuredJvmVersionOrNull = jvm2fmtMaxVersion.floorKey(Jvm.version());
124+
return (null == configuredJvmVersionOrNull) ? null : jvm2fmtMaxVersion.get(configuredJvmVersionOrNull);
125+
}
126+
127+
@Nullable
128+
public V getMinimumRequiredFormatterVersion() {
129+
Integer configuredJvmVersionOrNull = jvm2fmtMinVersion.floorKey(Jvm.version());
130+
return (null == configuredJvmVersionOrNull) ? null : jvm2fmtMinVersion.get(configuredJvmVersionOrNull);
110131
}
111132

112133
/**
@@ -123,10 +144,17 @@ public void assertFormatterSupported(V formatterVersion) {
123144
}
124145

125146
private String buildUnsupportedFormatterMessage(V fmtVersion) {
147+
// check if the jvm version is to low for the formatter version
126148
int requiredJvmVersion = getRequiredJvmVersion(fmtVersion);
127149
if (Jvm.version() < requiredJvmVersion) {
128150
return buildUpgradeJvmMessage(fmtVersion) + "Upgrade your JVM or try " + toString();
129151
}
152+
// check if the formatter version is too low for the jvm version
153+
V minimumFormatterVersion = getMinimumRequiredFormatterVersion();
154+
if ((null != minimumFormatterVersion) && (fmtVersionComparator.compare(fmtVersion, minimumFormatterVersion) < 0)) {
155+
return String.format("You are running Spotless on JVM %d. This requires %s of at least %s (you are using %s).%n", Jvm.version(), fmtName, minimumFormatterVersion, fmtVersion);
156+
}
157+
// otherwise all is well
130158
return "";
131159
}
132160

@@ -137,7 +165,7 @@ private String buildUpgradeJvmMessage(V fmtVersion) {
137165
if (null != recommendedFmtVersionOrNull) {
138166
builder.append(String.format(", which limits you to %s %s.%n", fmtName, recommendedFmtVersionOrNull));
139167
} else {
140-
Entry<V, Integer> nextFmtVersionOrNull = fmt2jvmVersion.ceilingEntry(fmtVersion);
168+
Entry<V, Integer> nextFmtVersionOrNull = fmtMaxVersion2jvmVersion.ceilingEntry(fmtVersion);
141169
if (null != nextFmtVersionOrNull) {
142170
builder.append(String.format(". %s %s requires JVM %d+", fmtName, fmtVersion, nextFmtVersionOrNull.getValue()));
143171
}
@@ -147,12 +175,12 @@ private String buildUpgradeJvmMessage(V fmtVersion) {
147175
}
148176

149177
private int getRequiredJvmVersion(V fmtVersion) {
150-
Entry<V, Integer> entry = fmt2jvmVersion.ceilingEntry(fmtVersion);
178+
Entry<V, Integer> entry = fmtMaxVersion2jvmVersion.ceilingEntry(fmtVersion);
151179
if (null == entry) {
152-
entry = fmt2jvmVersion.lastEntry();
180+
entry = fmtMaxVersion2jvmVersion.lastEntry();
153181
}
154182
if (null != entry) {
155-
V maxKnownFmtVersion = jvm2fmtVersion.get(entry.getValue());
183+
V maxKnownFmtVersion = jvm2fmtMaxVersion.get(entry.getValue());
156184
if (fmtVersionComparator.compare(fmtVersion, maxKnownFmtVersion) <= 0) {
157185
return entry.getValue();
158186
}
@@ -170,15 +198,15 @@ public FormatterFunc suggestLaterVersionOnError(V formatterVersion, FormatterFun
170198
Objects.requireNonNull(formatterVersion);
171199
Objects.requireNonNull(originalFunc);
172200
final String hintUnsupportedProblem = buildUnsupportedFormatterMessage(formatterVersion);
173-
final String proposeDiffererntFormatter = hintUnsupportedProblem.isEmpty() ? buildUpgradeFormatterMessage(formatterVersion) : hintUnsupportedProblem;
174-
return proposeDiffererntFormatter.isEmpty() ? originalFunc : new FormatterFunc() {
201+
final String proposeDifferentFormatter = hintUnsupportedProblem.isEmpty() ? buildUpgradeFormatterMessage(formatterVersion) : hintUnsupportedProblem;
202+
return proposeDifferentFormatter.isEmpty() ? originalFunc : new FormatterFunc() {
175203

176204
@Override
177205
public String apply(String unix, File file) throws Exception {
178206
try {
179207
return originalFunc.apply(unix, file);
180208
} catch (Exception e) {
181-
throw new Exception(proposeDiffererntFormatter, e);
209+
throw new Exception(proposeDifferentFormatter, e);
182210
}
183211
}
184212

@@ -187,7 +215,7 @@ public String apply(String input) throws Exception {
187215
try {
188216
return originalFunc.apply(input);
189217
} catch (Exception e) {
190-
throw new Exception(proposeDiffererntFormatter, e);
218+
throw new Exception(proposeDifferentFormatter, e);
191219
}
192220
}
193221

@@ -196,16 +224,25 @@ public String apply(String input) throws Exception {
196224

197225
private String buildUpgradeFormatterMessage(V fmtVersion) {
198226
StringBuilder builder = new StringBuilder();
227+
// check if the formatter is not supported on this jvm
228+
V minimumFormatterVersion = getMinimumRequiredFormatterVersion();
199229
V recommendedFmtVersionOrNull = getRecommendedFormatterVersion();
200-
if (null != recommendedFmtVersionOrNull && (fmtVersionComparator.compare(fmtVersion, recommendedFmtVersionOrNull) < 0)) {
230+
if ((null != minimumFormatterVersion) && (fmtVersionComparator.compare(fmtVersion, minimumFormatterVersion) < 0)) {
231+
builder.append(String.format("You are running Spotless on JVM %d. This requires %s of at least %s.%n", Jvm.version(), fmtName, minimumFormatterVersion));
232+
builder.append(String.format("You are using %s %s.%n", fmtName, fmtVersion));
233+
if (null != recommendedFmtVersionOrNull) {
234+
builder.append(String.format("%s %s is the recommended version, which may have fixed this problem.%n", fmtName, recommendedFmtVersionOrNull));
235+
}
236+
// check if the formatter is outdated on this jvm
237+
} else if (null != recommendedFmtVersionOrNull && (fmtVersionComparator.compare(fmtVersion, recommendedFmtVersionOrNull) < 0)) {
201238
builder.append(String.format("%s %s is currently being used, but outdated.%n", fmtName, fmtVersion));
202239
builder.append(String.format("%s %s is the recommended version, which may have fixed this problem.%n", fmtName, recommendedFmtVersionOrNull));
203240
builder.append(String.format("%s %s requires JVM %d+.", fmtName, recommendedFmtVersionOrNull, getRequiredJvmVersion(recommendedFmtVersionOrNull)));
204241
} else {
205-
V higherFormatterVersionOrNull = fmt2jvmVersion.higherKey(fmtVersion);
242+
V higherFormatterVersionOrNull = fmtMaxVersion2jvmVersion.higherKey(fmtVersion);
206243
if (null != higherFormatterVersionOrNull) {
207244
builder.append(buildUpgradeJvmMessage(fmtVersion));
208-
Integer higherJvmVersion = fmt2jvmVersion.get(higherFormatterVersionOrNull);
245+
Integer higherJvmVersion = fmtMaxVersion2jvmVersion.get(higherFormatterVersionOrNull);
209246
builder.append(String.format("If you upgrade your JVM to %d+, then you can use %s %s, which may have fixed this problem.", higherJvmVersion, fmtName, higherFormatterVersionOrNull));
210247
}
211248
}
@@ -215,7 +252,7 @@ private String buildUpgradeFormatterMessage(V fmtVersion) {
215252
@Override
216253
public String toString() {
217254
return String.format("%s alternatives:%n", fmtName) +
218-
jvm2fmtVersion.entrySet().stream().map(
255+
jvm2fmtMaxVersion.entrySet().stream().map(
219256
e -> String.format("- Version %s requires JVM %d+", e.getValue(), e.getKey())).collect(Collectors.joining(System.lineSeparator()));
220257
}
221258

0 commit comments

Comments
 (0)