Skip to content

Commit a7e93c8

Browse files
authored
Support google-java-format's skip-reflowing-long-strings option (#929)
2 parents 169f9b5 + 2b4dd07 commit a7e93c8

27 files changed

+194
-31
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ 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+
### Added
14+
* Added support for `google-java-format`'s `skip-reflowing-long-strings` option ([#929](https://github.com/diffplug/spotless/pull/929))
1315

1416
## [2.15.3] - 2021-08-20
1517
### Changed

lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java

+39-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.diffplug.spotless.JarState;
2828
import com.diffplug.spotless.LineEnding;
2929
import com.diffplug.spotless.Provisioner;
30+
import com.diffplug.spotless.ThrowingEx.BiFunction;
3031
import com.diffplug.spotless.ThrowingEx.Function;
3132

3233
/** Wraps up <a href="https://github.com/google/google-java-format">google-java-format</a> as a FormatterStep. */
@@ -35,6 +36,7 @@ public class GoogleJavaFormatStep {
3536
private GoogleJavaFormatStep() {}
3637

3738
private static final String DEFAULT_STYLE = "GOOGLE";
39+
private static final boolean DEFAULT_REFLOW_LONG_STRINGS = false;
3840
static final String NAME = "google-java-format";
3941
static final String MAVEN_COORDINATE = "com.google.googlejavaformat:google-java-format:";
4042
static final String FORMATTER_CLASS = "com.google.googlejavaformat.java.Formatter";
@@ -56,6 +58,9 @@ private GoogleJavaFormatStep() {}
5658
private static final String IMPORT_ORDERER_CLASS = "com.google.googlejavaformat.java.ImportOrderer";
5759
private static final String IMPORT_ORDERER_METHOD = "reorderImports";
5860

61+
private static final String STRING_WRAPPER_CLASS = "com.google.googlejavaformat.java.StringWrapper";
62+
private static final String STRING_WRAPPER_METHOD = "wrap";
63+
5964
/** Creates a step which formats everything - code, import order, and unused imports. */
6065
public static FormatterStep create(Provisioner provisioner) {
6166
return create(defaultVersion(), provisioner);
@@ -68,11 +73,16 @@ public static FormatterStep create(String version, Provisioner provisioner) {
6873

6974
/** Creates a step which formats everything - code, import order, and unused imports. */
7075
public static FormatterStep create(String version, String style, Provisioner provisioner) {
76+
return create(version, style, provisioner, DEFAULT_REFLOW_LONG_STRINGS);
77+
}
78+
79+
/** Creates a step which formats everything - code, import order, and unused imports - and optionally reflows long strings. */
80+
public static FormatterStep create(String version, String style, Provisioner provisioner, boolean reflowLongStrings) {
7181
Objects.requireNonNull(version, "version");
7282
Objects.requireNonNull(style, "style");
7383
Objects.requireNonNull(provisioner, "provisioner");
7484
return FormatterStep.createLazy(NAME,
75-
() -> new State(NAME, version, style, provisioner),
85+
() -> new State(NAME, version, style, provisioner, reflowLongStrings),
7686
State::createFormat);
7787
}
7888

@@ -106,6 +116,10 @@ public static String defaultStyle() {
106116
return DEFAULT_STYLE;
107117
}
108118

119+
public static boolean defaultReflowLongStrings() {
120+
return DEFAULT_REFLOW_LONG_STRINGS;
121+
}
122+
109123
static final class State implements Serializable {
110124
private static final long serialVersionUID = 1L;
111125

@@ -114,16 +128,22 @@ static final class State implements Serializable {
114128
final String stepName;
115129
final String version;
116130
final String style;
131+
final boolean reflowLongStrings;
117132

118133
State(String stepName, String version, Provisioner provisioner) throws IOException {
119134
this(stepName, version, DEFAULT_STYLE, provisioner);
120135
}
121136

122137
State(String stepName, String version, String style, Provisioner provisioner) throws IOException {
138+
this(stepName, version, style, provisioner, DEFAULT_REFLOW_LONG_STRINGS);
139+
}
140+
141+
State(String stepName, String version, String style, Provisioner provisioner, boolean reflowLongStrings) throws IOException {
123142
this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner);
124143
this.stepName = stepName;
125144
this.version = version;
126145
this.style = style;
146+
this.reflowLongStrings = reflowLongStrings;
127147
}
128148

129149
@SuppressWarnings({"unchecked", "rawtypes"})
@@ -153,11 +173,14 @@ FormatterFunc createFormat() throws Exception {
153173
Class<?> importOrdererClass = classLoader.loadClass(IMPORT_ORDERER_CLASS);
154174
Method importOrdererMethod = importOrdererClass.getMethod(IMPORT_ORDERER_METHOD, String.class);
155175

176+
BiFunction<String, Object, String> reflowLongStrings = this.reflowLongStrings ? constructReflowLongStringsFunction(classLoader, formatterClazz) : (s, f) -> s;
177+
156178
return suggestJre11(input -> {
157179
String formatted = (String) formatterMethod.invoke(formatter, input);
158180
String removedUnused = removeUnused.apply(formatted);
159181
String sortedImports = (String) importOrdererMethod.invoke(null, removedUnused);
160-
return fixWindowsBug(sortedImports, version);
182+
String reflowedLongStrings = reflowLongStrings.apply(sortedImports, formatter);
183+
return fixWindowsBug(reflowedLongStrings, version);
161184
});
162185
}
163186

@@ -191,6 +214,20 @@ private static Function<String, String> constructRemoveUnusedFunction(ClassLoade
191214
}
192215
return removeUnused;
193216
}
217+
218+
private static BiFunction<String, Object, String> constructReflowLongStringsFunction(ClassLoader classLoader, Class<?> formatterClazz) throws NoSuchMethodException {
219+
Class<?> stringWrapperClass;
220+
try {
221+
stringWrapperClass = classLoader.loadClass(STRING_WRAPPER_CLASS);
222+
} catch (ClassNotFoundException e) {
223+
// google-java-format 1.7 or lower, which happen to be LATEST_VERSION_JRE_8, so rely on suggestJre11 for the error
224+
return (s, f) -> {
225+
throw e;
226+
};
227+
}
228+
Method stringWrapperMethod = stringWrapperClass.getMethod(STRING_WRAPPER_METHOD, String.class, formatterClazz);
229+
return (s, f) -> (String) stringWrapperMethod.invoke(null, s, f);
230+
}
194231
}
195232

196233
private static final boolean IS_WINDOWS = LineEnding.PLATFORM_NATIVE.str().equals("\r\n");

plugin-gradle/CHANGES.md

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

55
## [Unreleased]
6+
### Added
7+
* Added support for `google-java-format`'s `skip-reflowing-long-strings` option ([#929](https://github.com/diffplug/spotless/pull/929))
68

79
## [5.14.3] - 2021-08-20
810
### Changed

plugin-gradle/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ spotless {
112112
// don't need to set target, it is inferred from java
113113
114114
// apply a specific flavor of google-java-format
115-
googleJavaFormat('1.8').aosp()
115+
googleJavaFormat('1.8').aosp().reflowLongStrings()
116116
// make sure every file has the following copyright header.
117117
// optionally, Spotless can set copyright years by digging
118118
// through git history (see "license" section below)
@@ -176,9 +176,9 @@ spotless {
176176
spotless {
177177
java {
178178
googleJavaFormat()
179-
// optional: you can specify a specific version and/or switch to AOSP style
179+
// optional: you can specify a specific version and/or switch to AOSP style and/or reflow long strings (requires at least 1.8)
180180
//
181-
googleJavaFormat('1.7').aosp()
181+
googleJavaFormat('1.8').aosp().reflowLongStrings()
182182
```
183183

184184
### eclipse jdt

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

+17-4
Original file line numberDiff line numberDiff line change
@@ -90,26 +90,39 @@ public GoogleJavaFormatConfig googleJavaFormat(String version) {
9090
public class GoogleJavaFormatConfig {
9191
final String version;
9292
String style;
93+
boolean reflowLongStrings;
9394

9495
GoogleJavaFormatConfig(String version) {
9596
this.version = Objects.requireNonNull(version);
9697
this.style = GoogleJavaFormatStep.defaultStyle();
9798
addStep(createStep());
9899
}
99100

100-
public void style(String style) {
101+
public GoogleJavaFormatConfig style(String style) {
101102
this.style = Objects.requireNonNull(style);
102103
replaceStep(createStep());
104+
return this;
103105
}
104106

105-
public void aosp() {
106-
style("AOSP");
107+
public GoogleJavaFormatConfig aosp() {
108+
return style("AOSP");
109+
}
110+
111+
public GoogleJavaFormatConfig reflowLongStrings() {
112+
return reflowLongStrings(true);
113+
}
114+
115+
public GoogleJavaFormatConfig reflowLongStrings(boolean reflowLongStrings) {
116+
this.reflowLongStrings = reflowLongStrings;
117+
replaceStep(createStep());
118+
return this;
107119
}
108120

109121
private FormatterStep createStep() {
110122
return GoogleJavaFormatStep.create(version,
111123
style,
112-
provisioner());
124+
provisioner(),
125+
reflowLongStrings);
113126
}
114127
}
115128

plugin-maven/CHANGES.md

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

55
## [Unreleased]
6+
### Added
7+
* Added support for `google-java-format`'s `skip-reflowing-long-strings` option ([#929](https://github.com/diffplug/spotless/pull/929))
68

79
## [2.12.3] - 2021-08-20
810
### Changed

plugin-maven/README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,11 @@ To use it in your pom, just [add the Spotless dependency](https://search.maven.o
105105
<java>
106106
<!-- no need to specify files, inferred automatically, but you can if you want -->
107107

108-
<!-- apply a specific flavor of google-java-format -->
108+
<!-- apply a specific flavor of google-java-format and reflow long strings -->
109109
<googleJavaFormat>
110110
<version>1.8</version>
111111
<style>AOSP</style>
112+
<reflowLongStrings>true</reflowLongStrings>
112113
</googleJavaFormat>
113114

114115
<!-- make sure every file has the following copyright header.
@@ -201,8 +202,9 @@ any other maven phase (i.e. compile) then it can be configured as below;
201202

202203
```xml
203204
<googleJavaFormat>
204-
<version>1.7</version> <!-- optional -->
205-
<style>GOOGLE</style> <!-- or AOSP (optional) -->
205+
<version>1.8</version> <!-- optional -->
206+
<style>GOOGLE</style> <!-- or AOSP (optional) -->
207+
<reflowLongStrings>true</reflowLongStrings> <!-- optional (requires at least 1.8) -->
206208
</googleJavaFormat>
207209
```
208210

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 DiffPlug
2+
* Copyright 2016-2021 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,10 +29,14 @@ public class GoogleJavaFormat implements FormatterStepFactory {
2929
@Parameter
3030
private String style;
3131

32+
@Parameter
33+
private Boolean reflowLongStrings;
34+
3235
@Override
3336
public FormatterStep newFormatterStep(FormatterStepConfig config) {
3437
String version = this.version != null ? this.version : GoogleJavaFormatStep.defaultVersion();
3538
String style = this.style != null ? this.style : GoogleJavaFormatStep.defaultStyle();
36-
return GoogleJavaFormatStep.create(version, style, config.getProvisioner());
39+
boolean reflowLongStrings = this.reflowLongStrings != null ? this.reflowLongStrings : GoogleJavaFormatStep.defaultReflowLongStrings();
40+
return GoogleJavaFormatStep.create(version, style, config.getProvisioner(), reflowLongStrings);
3741
}
3842
}

plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2020 DiffPlug
2+
* Copyright 2016-2021 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717

1818
import org.junit.Test;
1919

20+
import com.diffplug.spotless.JreVersion;
2021
import com.diffplug.spotless.maven.MavenIntegrationHarness;
2122

2223
public class GoogleJavaFormatTest extends MavenIntegrationHarness {
@@ -41,6 +42,18 @@ public void specificVersionSpecificStyle() throws Exception {
4142
runTest("java/googlejavaformat/JavaCodeFormattedAOSP.test");
4243
}
4344

45+
@Test
46+
public void specificVersionReflowLongStrings() throws Exception {
47+
JreVersion.assume11OrGreater();
48+
writePomWithJavaSteps(
49+
"<googleJavaFormat>",
50+
" <version>1.8</version>",
51+
" <reflowLongStrings>true</reflowLongStrings>",
52+
"</googleJavaFormat>");
53+
54+
runTest("java/googlejavaformat/JavaCodeFormattedReflowLongStrings.test");
55+
}
56+
4457
private void runTest(String targetResource) throws Exception {
4558
String path = "src/main/java/test.java";
4659
setFile(path).toResource("java/googlejavaformat/JavaCodeUnformatted.test");

testlib/src/main/resources/java/googlejavaformat/JavaCodeFormatted.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import mylib.UsedB;
44

55
public class Java {
66
public static void main(String[] args) {
7-
System.out.println("hello");
7+
System.out.println(
8+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
89
UsedB.someMethod();
910
UsedA.someMethod();
1011
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeFormatted18.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import mylib.UsedB;
33

44
public class Java {
55
public static void main(String[] args) {
6-
System.out.println("hello");
6+
System.out.println(
7+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
78
UsedB.someMethod();
89
UsedA.someMethod();
910
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeFormattedAOSP.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import mylib.UsedB;
44

55
public class Java {
66
public static void main(String[] args) {
7-
System.out.println("hello");
7+
System.out.println(
8+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
89
UsedB.someMethod();
910
UsedA.someMethod();
1011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import mylib.UsedA;
2+
import mylib.UsedB;
3+
4+
public class Java {
5+
public static void main(String[] args) {
6+
System.out.println(
7+
"A very very very very very very very very very very very very very very very very very"
8+
+ " very very very very long string that goes beyond the 100-character line length.");
9+
UsedB.someMethod();
10+
UsedA.someMethod();
11+
}
12+
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeUnformatted.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import mylib.UsedA;
55

66
public class Java {
77
public static void main(String[] args) {
8-
System.out.println("hello");
8+
System.out.println("A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
99
UsedB.someMethod();
1010
UsedA.someMethod();
1111
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeWithLicenseFormatted.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import mylib.UsedB;
88

99
public class Java {
1010
public static void main(String[] args) {
11-
System.out.println("hello");
11+
System.out.println(
12+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
1213
UsedB.someMethod();
1314
UsedA.someMethod();
1415
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeWithLicenseFormattedAOSP.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import mylib.UsedB;
88

99
public class Java {
1010
public static void main(String[] args) {
11-
System.out.println("hello");
11+
System.out.println(
12+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
1213
UsedB.someMethod();
1314
UsedA.someMethod();
1415
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Some license stuff.
3+
* Very official.
4+
*/
5+
6+
import mylib.UsedA;
7+
import mylib.UsedB;
8+
9+
public class Java {
10+
public static void main(String[] args) {
11+
System.out.println(
12+
"A very very very very very very very very very very very very very very very very very"
13+
+ " very very very very long string that goes beyond the 100-character line length.");
14+
UsedB.someMethod();
15+
UsedA.someMethod();
16+
}
17+
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeWithLicensePackageFormatted.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import mylib.UsedB;
55

66
public class Java {
77
public static void main(String[] args) {
8-
System.out.println("hello");
8+
System.out.println(
9+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
910
UsedB.someMethod();
1011
UsedA.someMethod();
1112
}

testlib/src/main/resources/java/googlejavaformat/JavaCodeWithLicensePackageFormattedAOSP.test

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import mylib.UsedB;
55

66
public class Java {
77
public static void main(String[] args) {
8-
System.out.println("hello");
8+
System.out.println(
9+
"A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length.");
910
UsedB.someMethod();
1011
UsedA.someMethod();
1112
}

0 commit comments

Comments
 (0)