Skip to content

Commit de2d9b6

Browse files
authored
Merge pull request #563 from benkard/mulk/feature/google-java-format-1.8
Support google-java-format 1.8+
2 parents 608af5c + 0104f6d commit de2d9b6

File tree

17 files changed

+290
-31
lines changed

17 files changed

+290
-31
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: java
22
jdk:
33
- openjdk8
4+
- openjdk11
45
env:
56
- NODE_VERSION="6.10.2"
67
before_install:

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+
* Support for google-java-format 1.8 (including test infrastructure for Java 11). ([#562](https://github.com/diffplug/spotless/issues/562))
1315

1416
## [1.28.1] - 2020-04-02
1517
### Fixed

gradle/java-publish.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ task sourcesJar(type: Jar) {
1515
// Thus, no javadoc warnings.
1616
javadoc {
1717
options.addStringOption('Xdoclint:none', '-quiet')
18+
enabled = org.gradle.api.JavaVersion.current() == org.gradle.api.JavaVersion.VERSION_1_8
1819
}
1920

2021
// use markdown in javadoc

gradle/java-setup.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ spotbugs {
4646
}
4747
// HTML instead of XML
4848
tasks.withType(spotBugsTaskType()) {
49+
// only run on Java 8 (no benefit to running twice)
50+
enabled = org.gradle.api.JavaVersion.current() == org.gradle.api.JavaVersion.VERSION_1_8
4951
reports {
5052
xml.enabled = false
5153
html.enabled = true

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

+28-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.diffplug.spotless.JarState;
2626
import com.diffplug.spotless.LineEnding;
2727
import com.diffplug.spotless.Provisioner;
28+
import com.diffplug.spotless.ThrowingEx.Function;
2829

2930
/** Wraps up [google-java-format](https://github.com/google/google-java-format) as a FormatterStep. */
3031
public class GoogleJavaFormatStep {
@@ -124,17 +125,14 @@ FormatterFunc createFormat() throws Exception {
124125
Object formatter = formatterClazz.getConstructor(optionsClass).newInstance(options);
125126
Method formatterMethod = formatterClazz.getMethod(FORMATTER_METHOD, String.class);
126127

127-
Class<?> removeUnusedClass = classLoader.loadClass(REMOVE_UNUSED_CLASS);
128-
Class<?> removeJavadocOnlyClass = classLoader.loadClass(REMOVE_UNUSED_IMPORT_JavadocOnlyImports);
129-
Object removeJavadocConstant = Enum.valueOf((Class<Enum>) removeJavadocOnlyClass, REMOVE_UNUSED_IMPORT_JavadocOnlyImports_Keep);
130-
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class, removeJavadocOnlyClass);
128+
Function<String, String> removeUnused = constructRemoveUnusedFunction(classLoader);
131129

132130
Class<?> importOrdererClass = classLoader.loadClass(IMPORT_ORDERER_CLASS);
133131
Method importOrdererMethod = importOrdererClass.getMethod(IMPORT_ORDERER_METHOD, String.class);
134132

135133
return input -> {
136134
String formatted = (String) formatterMethod.invoke(formatter, input);
137-
String removedUnused = (String) removeUnusedMethod.invoke(null, formatted, removeJavadocConstant);
135+
String removedUnused = removeUnused.apply(formatted);
138136
String sortedImports = (String) importOrdererMethod.invoke(null, removedUnused);
139137
return fixWindowsBug(sortedImports, version);
140138
};
@@ -144,15 +142,33 @@ FormatterFunc createFormat() throws Exception {
144142
FormatterFunc createRemoveUnusedImportsOnly() throws Exception {
145143
ClassLoader classLoader = jarState.getClassLoader();
146144

145+
Function<String, String> removeUnused = constructRemoveUnusedFunction(classLoader);
146+
147+
return input -> fixWindowsBug(removeUnused.apply(input), version);
148+
}
149+
150+
private static Function<String, String> constructRemoveUnusedFunction(ClassLoader classLoader)
151+
throws NoSuchMethodException, ClassNotFoundException {
147152
Class<?> removeUnusedClass = classLoader.loadClass(REMOVE_UNUSED_CLASS);
148-
Class<?> removeJavadocOnlyClass = classLoader.loadClass(REMOVE_UNUSED_IMPORT_JavadocOnlyImports);
149-
Object removeJavadocConstant = Enum.valueOf((Class<Enum>) removeJavadocOnlyClass, REMOVE_UNUSED_IMPORT_JavadocOnlyImports_Keep);
150-
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class, removeJavadocOnlyClass);
153+
Class<?> removeJavadocOnlyClass;
154+
try {
155+
// google-java-format 1.7 or lower
156+
removeJavadocOnlyClass = classLoader.loadClass(REMOVE_UNUSED_IMPORT_JavadocOnlyImports);
157+
} catch (ClassNotFoundException e) {
158+
// google-java-format 1.8+
159+
removeJavadocOnlyClass = null;
160+
}
151161

152-
return input -> {
153-
String removeUnused = (String) removeUnusedMethod.invoke(null, input, removeJavadocConstant);
154-
return fixWindowsBug(removeUnused, version);
155-
};
162+
Function<String, String> removeUnused;
163+
if (removeJavadocOnlyClass != null) {
164+
Object removeJavadocConstant = Enum.valueOf((Class<Enum>) removeJavadocOnlyClass, REMOVE_UNUSED_IMPORT_JavadocOnlyImports_Keep);
165+
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class, removeJavadocOnlyClass);
166+
removeUnused = (x) -> (String) removeUnusedMethod.invoke(null, x, removeJavadocConstant);
167+
} else {
168+
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class);
169+
removeUnused = (x) -> (String) removeUnusedMethod.invoke(null, x);
170+
}
171+
return removeUnused;
156172
}
157173
}
158174

plugin-gradle/CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
55
## [Unreleased]
66

77
## [3.28.1] - 2020-04-02
8+
### Added
9+
* Support for google-java-format 1.8 (requires you to run build on Java 11) ([#562](https://github.com/diffplug/spotless/issues/562))
810
### Fixed
911
* Eclipse-WTP formatter (web tools platform, not java) handles some character encodings incorrectly on OS with non-unicode default file encoding [#545](https://github.com/diffplug/spotless/issues/545). Fixed for Eclipse-WTP formatter Eclipse version 4.13.0 (default version).
1012

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright 2016 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+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.List;
22+
23+
import org.assertj.core.api.Assertions;
24+
import org.gradle.testkit.runner.BuildResult;
25+
import org.gradle.testkit.runner.TaskOutcome;
26+
import org.junit.Test;
27+
28+
import com.diffplug.common.base.CharMatcher;
29+
import com.diffplug.common.base.Splitter;
30+
import com.diffplug.common.base.StringPrinter;
31+
import com.diffplug.spotless.JreVersion;
32+
import com.diffplug.spotless.LineEnding;
33+
34+
/** Tests the desired behavior from https://github.com/diffplug/spotless/issues/46. */
35+
public class ErrorShouldRethrowJre11 extends GradleIntegrationTest {
36+
private void writeBuild(String... toInsert) throws IOException {
37+
List<String> lines = new ArrayList<>();
38+
lines.add("plugins {");
39+
lines.add(" id 'com.diffplug.gradle.spotless'");
40+
lines.add(" id 'java'");
41+
lines.add("}");
42+
lines.add("spotless {");
43+
lines.add(" format 'misc', {");
44+
lines.add(" lineEndings 'UNIX'");
45+
lines.add(" target file('README.md')");
46+
lines.add(" custom 'no swearing', {");
47+
lines.add(" if (it.toLowerCase(Locale.ROOT).contains('fubar')) {");
48+
lines.add(" throw new RuntimeException('No swearing!');");
49+
lines.add(" }");
50+
lines.add(" }");
51+
lines.addAll(Arrays.asList(toInsert));
52+
setFile("build.gradle").toContent(String.join("\n", lines));
53+
}
54+
55+
@Test
56+
public void passesIfNoException() throws Exception {
57+
writeBuild(
58+
" } // format",
59+
"} // spotless");
60+
setFile("README.md").toContent("This code is fun.");
61+
runWithSuccess("> Task :spotlessMisc");
62+
}
63+
64+
@Test
65+
public void anyExceptionShouldFail() throws Exception {
66+
writeBuild(
67+
" } // format",
68+
"} // spotless");
69+
setFile("README.md").toContent("This code is fubar.");
70+
runWithFailure(
71+
"> Task :spotlessMisc FAILED\n" +
72+
"Step 'no swearing' found problem in 'README.md':\n" +
73+
"No swearing!\n" +
74+
"java.lang.RuntimeException: No swearing!\n");
75+
}
76+
77+
@Test
78+
public void unlessEnforceCheckIsFalse() throws Exception {
79+
writeBuild(
80+
" } // format",
81+
" enforceCheck false",
82+
"} // spotless");
83+
setFile("README.md").toContent("This code is fubar.");
84+
runWithSuccess("> Task :compileJava NO-SOURCE");
85+
}
86+
87+
@Test
88+
public void unlessExemptedByStep() throws Exception {
89+
writeBuild(
90+
" ignoreErrorForStep 'no swearing'",
91+
" } // format",
92+
"} // spotless");
93+
setFile("README.md").toContent("This code is fubar.");
94+
runWithSuccess("> Task :spotlessMisc\n" +
95+
"Unable to apply step 'no swearing' to 'README.md'");
96+
}
97+
98+
@Test
99+
public void unlessExemptedByPath() throws Exception {
100+
writeBuild(
101+
" ignoreErrorForPath 'README.md'",
102+
" } // format",
103+
"} // spotless");
104+
setFile("README.md").toContent("This code is fubar.");
105+
runWithSuccess("> Task :spotlessMisc",
106+
"Unable to apply step 'no swearing' to 'README.md'");
107+
}
108+
109+
@Test
110+
public void failsIfNeitherStepNorFileExempted() throws Exception {
111+
writeBuild(
112+
" ignoreErrorForStep 'nope'",
113+
" ignoreErrorForPath 'nope'",
114+
" } // format",
115+
"} // spotless");
116+
setFile("README.md").toContent("This code is fubar.");
117+
runWithFailure("> Task :spotlessMisc FAILED\n" +
118+
"Step 'no swearing' found problem in 'README.md':\n" +
119+
"No swearing!\n" +
120+
"java.lang.RuntimeException: No swearing!\n");
121+
}
122+
123+
private void runWithSuccess(String... messages) throws Exception {
124+
if (JreVersion.thisVm() != JreVersion._11) {
125+
return;
126+
}
127+
BuildResult result = gradleRunner().withArguments("check").build();
128+
assertResultAndMessages(result, TaskOutcome.SUCCESS, messages);
129+
}
130+
131+
private void runWithFailure(String... messages) throws Exception {
132+
if (JreVersion.thisVm() != JreVersion._11) {
133+
return;
134+
}
135+
BuildResult result = gradleRunner().withArguments("check").buildAndFail();
136+
assertResultAndMessages(result, TaskOutcome.FAILED, messages);
137+
}
138+
139+
private void assertResultAndMessages(BuildResult result, TaskOutcome outcome, String... messages) {
140+
String expectedToStartWith = StringPrinter.buildStringFromLines(messages).trim();
141+
int numNewlines = CharMatcher.is('\n').countIn(expectedToStartWith);
142+
List<String> actualLines = Splitter.on('\n').splitToList(LineEnding.toUnix(result.getOutput().trim()));
143+
String actualStart = String.join("\n", actualLines.subList(0, numNewlines + 1));
144+
Assertions.assertThat(actualStart).isEqualTo(expectedToStartWith);
145+
Assertions.assertThat(result.tasks(outcome).size() + result.tasks(TaskOutcome.UP_TO_DATE).size() + result.tasks(TaskOutcome.NO_SOURCE).size())
146+
.isEqualTo(result.getTasks().size());
147+
}
148+
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrow.java renamed to plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrowJre8.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
import com.diffplug.common.base.CharMatcher;
2929
import com.diffplug.common.base.Splitter;
3030
import com.diffplug.common.base.StringPrinter;
31+
import com.diffplug.spotless.JreVersion;
3132
import com.diffplug.spotless.LineEnding;
3233

3334
/** Tests the desired behavior from https://github.com/diffplug/spotless/issues/46. */
34-
public class ErrorShouldRethrow extends GradleIntegrationTest {
35+
public class ErrorShouldRethrowJre8 extends GradleIntegrationTest {
3536
private void writeBuild(String... toInsert) throws IOException {
3637
List<String> lines = new ArrayList<>();
3738
lines.add("plugins {");
@@ -119,11 +120,17 @@ public void failsIfNeitherStepNorFileExempted() throws Exception {
119120
}
120121

121122
private void runWithSuccess(String... messages) throws Exception {
123+
if (JreVersion.thisVm() != JreVersion._8) {
124+
return;
125+
}
122126
BuildResult result = gradleRunner().withArguments("check").build();
123127
assertResultAndMessages(result, TaskOutcome.SUCCESS, messages);
124128
}
125129

126130
private void runWithFailure(String... messages) throws Exception {
131+
if (JreVersion.thisVm() != JreVersion._8) {
132+
return;
133+
}
127134
BuildResult result = gradleRunner().withArguments("check").buildAndFail();
128135
assertResultAndMessages(result, TaskOutcome.FAILED, messages);
129136
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.diffplug.common.base.StringPrinter;
3434
import com.diffplug.common.tree.TreeDef;
3535
import com.diffplug.common.tree.TreeStream;
36+
import com.diffplug.spotless.JreVersion;
3637
import com.diffplug.spotless.LineEnding;
3738
import com.diffplug.spotless.ResourceHarness;
3839

@@ -56,11 +57,25 @@ public void gitAttributes() throws IOException {
5657
setFile(".gitattributes").toContent("* text eol=lf");
5758
}
5859

60+
/**
61+
* For Java 11+, Gradle 5 is the minimum.
62+
* So if you ask for less than Gradle 5, you get it on Java 8, but on Java 11 you get promoted to Gradle 5.
63+
* If you ask for more than Gradle 5, you'll definitely get it.
64+
*/
65+
protected static String requestGradleForJre8and11(String ver) {
66+
JreVersion jre = JreVersion.thisVm();
67+
// @formatter:off
68+
switch (jre) {
69+
case _8: return ver;
70+
case _11: return Double.parseDouble(ver) < 5.0 ? "5.0" : ver;
71+
default: throw new IllegalStateException("Spotless build is only supported on Java 8 and Java 11");
72+
}
73+
// @formatter:on
74+
}
75+
5976
protected final GradleRunner gradleRunner() throws IOException {
6077
return GradleRunner.create()
61-
// Test against Gradle 2.14.1 in order to maintain backwards compatibility.
62-
// https://github.com/diffplug/spotless/issues/161
63-
.withGradleVersion("2.14.1")
78+
.withGradleVersion(requestGradleForJre8and11("2.14"))
6479
.withProjectDir(rootFolder())
6580
.withPluginClasspath();
6681
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/HasBuiltinDelimiterForLicenseTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void testWithCommonInterfaceForConfiguringLicences() throws IOException {
4949
" }",
5050
"}");
5151
gradleRunner()
52-
.withGradleVersion("4.6")
52+
.withGradleVersion(requestGradleForJre8and11("4.6")) // 4.6 is the min
5353
.withArguments("spotlessApply")
5454
.forwardOutput()
5555
.build();

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/RegisterDependenciesTaskTest.java

+14-10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.assertj.core.api.Assertions;
2121
import org.junit.Test;
2222

23+
import com.diffplug.spotless.JreVersion;
24+
2325
public class RegisterDependenciesTaskTest extends GradleIntegrationTest {
2426
@Test
2527
public void registerDependencies() throws IOException {
@@ -38,16 +40,18 @@ public void registerDependencies() throws IOException {
3840
" }",
3941
"}");
4042

41-
String oldestSupported = gradleRunner()
42-
.withArguments("spotlessCheck").build().getOutput();
43-
Assertions.assertThat(oldestSupported.replace("\r", "")).startsWith(
44-
":spotlessCheck UP-TO-DATE\n" +
45-
":spotlessInternalRegisterDependencies\n" +
46-
":sub:spotlessJava\n" +
47-
":sub:spotlessJavaCheck\n" +
48-
":sub:spotlessCheck\n" +
49-
"\n" +
50-
"BUILD SUCCESSFUL");
43+
if (JreVersion.thisVm() == JreVersion._8) {
44+
String oldestSupported = gradleRunner()
45+
.withArguments("spotlessCheck").build().getOutput();
46+
Assertions.assertThat(oldestSupported.replace("\r", "")).startsWith(
47+
":spotlessCheck UP-TO-DATE\n" +
48+
":spotlessInternalRegisterDependencies\n" +
49+
":sub:spotlessJava\n" +
50+
":sub:spotlessJavaCheck\n" +
51+
":sub:spotlessCheck\n" +
52+
"\n" +
53+
"BUILD SUCCESSFUL");
54+
}
5155

5256
setFile("gradle.properties").toLines();
5357
String newestSupported = gradleRunner().withGradleVersion("6.0")

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/SpecificFilesTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private void integration(String patterns,
103103
GradleRunner runner = gradleRunner()
104104
.withArguments("spotlessApply", "-PspotlessFiles=" + patterns);
105105
if (isKotlin) {
106-
runner.withGradleVersion("4.0");
106+
runner.withGradleVersion(requestGradleForJre8and11("4.0"));
107107
}
108108
runner.build();
109109

plugin-maven/CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
77
## [1.30.0] - 2020-04-10
88
### Added
99
* Support for prettier ([#555](https://github.com/diffplug/spotless/pull/555)).
10+
* Support for google-java-format 1.8 (requires you to run build on Java 11) ([#562](https://github.com/diffplug/spotless/issues/562))
1011

1112
## [1.29.0] - 2020-04-02
1213
### Added

0 commit comments

Comments
 (0)