Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support google-java-format 1.8+ #563

Merged
merged 13 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: java
jdk:
- openjdk8
- openjdk11
env:
- NODE_VERSION="6.10.2"
before_install:
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ 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]
### Added
* Support for google-java-format 1.8 (including test infrastructure for Java 11). ([#562](https://github.com/diffplug/spotless/issues/562))

## [1.28.1] - 2020-04-02
### Fixed
Expand Down
1 change: 1 addition & 0 deletions gradle/java-publish.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ task sourcesJar(type: Jar) {
// Thus, no javadoc warnings.
javadoc {
options.addStringOption('Xdoclint:none', '-quiet')
enabled = org.gradle.api.JavaVersion.current() == org.gradle.api.JavaVersion.VERSION_1_8
}

// use markdown in javadoc
Expand Down
2 changes: 2 additions & 0 deletions gradle/java-setup.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ spotbugs {
}
// HTML instead of XML
tasks.withType(spotBugsTaskType()) {
// only run on Java 8 (no benefit to running twice)
enabled = org.gradle.api.JavaVersion.current() == org.gradle.api.JavaVersion.VERSION_1_8
reports {
xml.enabled = false
html.enabled = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.diffplug.spotless.JarState;
import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.Provisioner;
import com.diffplug.spotless.ThrowingEx.Function;

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

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

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

return input -> {
String formatted = (String) formatterMethod.invoke(formatter, input);
String removedUnused = (String) removeUnusedMethod.invoke(null, formatted, removeJavadocConstant);
String removedUnused = removeUnused.apply(formatted);
String sortedImports = (String) importOrdererMethod.invoke(null, removedUnused);
return fixWindowsBug(sortedImports, version);
};
Expand All @@ -144,15 +142,33 @@ FormatterFunc createFormat() throws Exception {
FormatterFunc createRemoveUnusedImportsOnly() throws Exception {
ClassLoader classLoader = jarState.getClassLoader();

Function<String, String> removeUnused = constructRemoveUnusedFunction(classLoader);

return input -> fixWindowsBug(removeUnused.apply(input), version);
}

private static Function<String, String> constructRemoveUnusedFunction(ClassLoader classLoader)
throws NoSuchMethodException, ClassNotFoundException {
Class<?> removeUnusedClass = classLoader.loadClass(REMOVE_UNUSED_CLASS);
Class<?> removeJavadocOnlyClass = classLoader.loadClass(REMOVE_UNUSED_IMPORT_JavadocOnlyImports);
Object removeJavadocConstant = Enum.valueOf((Class<Enum>) removeJavadocOnlyClass, REMOVE_UNUSED_IMPORT_JavadocOnlyImports_Keep);
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class, removeJavadocOnlyClass);
Class<?> removeJavadocOnlyClass;
try {
// google-java-format 1.7 or lower
removeJavadocOnlyClass = classLoader.loadClass(REMOVE_UNUSED_IMPORT_JavadocOnlyImports);
} catch (ClassNotFoundException e) {
// google-java-format 1.8+
removeJavadocOnlyClass = null;
}

return input -> {
String removeUnused = (String) removeUnusedMethod.invoke(null, input, removeJavadocConstant);
return fixWindowsBug(removeUnused, version);
};
Function<String, String> removeUnused;
if (removeJavadocOnlyClass != null) {
Object removeJavadocConstant = Enum.valueOf((Class<Enum>) removeJavadocOnlyClass, REMOVE_UNUSED_IMPORT_JavadocOnlyImports_Keep);
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class, removeJavadocOnlyClass);
removeUnused = (x) -> (String) removeUnusedMethod.invoke(null, x, removeJavadocConstant);
} else {
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class);
removeUnused = (x) -> (String) removeUnusedMethod.invoke(null, x);
}
return removeUnused;
}
}

Expand Down
2 changes: 2 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]

## [3.28.1] - 2020-04-02
### Added
* Support for google-java-format 1.8 (requires you to run build on Java 11) ([#562](https://github.com/diffplug/spotless/issues/562))
### Fixed
* 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).

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright 2016 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 java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.assertj.core.api.Assertions;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.Test;

import com.diffplug.common.base.CharMatcher;
import com.diffplug.common.base.Splitter;
import com.diffplug.common.base.StringPrinter;
import com.diffplug.spotless.JreVersion;
import com.diffplug.spotless.LineEnding;

/** Tests the desired behavior from https://github.com/diffplug/spotless/issues/46. */
public class ErrorShouldRethrowJre11 extends GradleIntegrationTest {
private void writeBuild(String... toInsert) throws IOException {
List<String> lines = new ArrayList<>();
lines.add("plugins {");
lines.add(" id 'com.diffplug.gradle.spotless'");
lines.add(" id 'java'");
lines.add("}");
lines.add("spotless {");
lines.add(" format 'misc', {");
lines.add(" lineEndings 'UNIX'");
lines.add(" target file('README.md')");
lines.add(" custom 'no swearing', {");
lines.add(" if (it.toLowerCase(Locale.ROOT).contains('fubar')) {");
lines.add(" throw new RuntimeException('No swearing!');");
lines.add(" }");
lines.add(" }");
lines.addAll(Arrays.asList(toInsert));
setFile("build.gradle").toContent(String.join("\n", lines));
}

@Test
public void passesIfNoException() throws Exception {
writeBuild(
" } // format",
"} // spotless");
setFile("README.md").toContent("This code is fun.");
runWithSuccess("> Task :spotlessMisc");
}

@Test
public void anyExceptionShouldFail() throws Exception {
writeBuild(
" } // format",
"} // spotless");
setFile("README.md").toContent("This code is fubar.");
runWithFailure(
"> Task :spotlessMisc FAILED\n" +
"Step 'no swearing' found problem in 'README.md':\n" +
"No swearing!\n" +
"java.lang.RuntimeException: No swearing!\n");
}

@Test
public void unlessEnforceCheckIsFalse() throws Exception {
writeBuild(
" } // format",
" enforceCheck false",
"} // spotless");
setFile("README.md").toContent("This code is fubar.");
runWithSuccess("> Task :compileJava NO-SOURCE");
}

@Test
public void unlessExemptedByStep() throws Exception {
writeBuild(
" ignoreErrorForStep 'no swearing'",
" } // format",
"} // spotless");
setFile("README.md").toContent("This code is fubar.");
runWithSuccess("> Task :spotlessMisc\n" +
"Unable to apply step 'no swearing' to 'README.md'");
}

@Test
public void unlessExemptedByPath() throws Exception {
writeBuild(
" ignoreErrorForPath 'README.md'",
" } // format",
"} // spotless");
setFile("README.md").toContent("This code is fubar.");
runWithSuccess("> Task :spotlessMisc",
"Unable to apply step 'no swearing' to 'README.md'");
}

@Test
public void failsIfNeitherStepNorFileExempted() throws Exception {
writeBuild(
" ignoreErrorForStep 'nope'",
" ignoreErrorForPath 'nope'",
" } // format",
"} // spotless");
setFile("README.md").toContent("This code is fubar.");
runWithFailure("> Task :spotlessMisc FAILED\n" +
"Step 'no swearing' found problem in 'README.md':\n" +
"No swearing!\n" +
"java.lang.RuntimeException: No swearing!\n");
}

private void runWithSuccess(String... messages) throws Exception {
if (JreVersion.thisVm() != JreVersion._11) {
return;
}
BuildResult result = gradleRunner().withArguments("check").build();
assertResultAndMessages(result, TaskOutcome.SUCCESS, messages);
}

private void runWithFailure(String... messages) throws Exception {
if (JreVersion.thisVm() != JreVersion._11) {
return;
}
BuildResult result = gradleRunner().withArguments("check").buildAndFail();
assertResultAndMessages(result, TaskOutcome.FAILED, messages);
}

private void assertResultAndMessages(BuildResult result, TaskOutcome outcome, String... messages) {
String expectedToStartWith = StringPrinter.buildStringFromLines(messages).trim();
int numNewlines = CharMatcher.is('\n').countIn(expectedToStartWith);
List<String> actualLines = Splitter.on('\n').splitToList(LineEnding.toUnix(result.getOutput().trim()));
String actualStart = String.join("\n", actualLines.subList(0, numNewlines + 1));
Assertions.assertThat(actualStart).isEqualTo(expectedToStartWith);
Assertions.assertThat(result.tasks(outcome).size() + result.tasks(TaskOutcome.UP_TO_DATE).size() + result.tasks(TaskOutcome.NO_SOURCE).size())
.isEqualTo(result.getTasks().size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
import com.diffplug.common.base.CharMatcher;
import com.diffplug.common.base.Splitter;
import com.diffplug.common.base.StringPrinter;
import com.diffplug.spotless.JreVersion;
import com.diffplug.spotless.LineEnding;

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

private void runWithSuccess(String... messages) throws Exception {
if (JreVersion.thisVm() != JreVersion._8) {
return;
}
BuildResult result = gradleRunner().withArguments("check").build();
assertResultAndMessages(result, TaskOutcome.SUCCESS, messages);
}

private void runWithFailure(String... messages) throws Exception {
if (JreVersion.thisVm() != JreVersion._8) {
return;
}
BuildResult result = gradleRunner().withArguments("check").buildAndFail();
assertResultAndMessages(result, TaskOutcome.FAILED, messages);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.diffplug.common.base.StringPrinter;
import com.diffplug.common.tree.TreeDef;
import com.diffplug.common.tree.TreeStream;
import com.diffplug.spotless.JreVersion;
import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.ResourceHarness;

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

/**
* For Java 11+, Gradle 5 is the minimum.
* 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.
* If you ask for more than Gradle 5, you'll definitely get it.
*/
protected static String requestGradleForJre8and11(String ver) {
JreVersion jre = JreVersion.thisVm();
// @formatter:off
switch (jre) {
case _8: return ver;
case _11: return Double.parseDouble(ver) < 5.0 ? "5.0" : ver;
default: throw new IllegalStateException("Spotless build is only supported on Java 8 and Java 11");
}
// @formatter:on
}

protected final GradleRunner gradleRunner() throws IOException {
return GradleRunner.create()
// Test against Gradle 2.14.1 in order to maintain backwards compatibility.
// https://github.com/diffplug/spotless/issues/161
.withGradleVersion("2.14.1")
.withGradleVersion(requestGradleForJre8and11("2.14"))
.withProjectDir(rootFolder())
.withPluginClasspath();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void testWithCommonInterfaceForConfiguringLicences() throws IOException {
" }",
"}");
gradleRunner()
.withGradleVersion("4.6")
.withGradleVersion(requestGradleForJre8and11("4.6")) // 4.6 is the min
.withArguments("spotlessApply")
.forwardOutput()
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import org.assertj.core.api.Assertions;
import org.junit.Test;

import com.diffplug.spotless.JreVersion;

public class RegisterDependenciesTaskTest extends GradleIntegrationTest {
@Test
public void registerDependencies() throws IOException {
Expand All @@ -38,16 +40,18 @@ public void registerDependencies() throws IOException {
" }",
"}");

String oldestSupported = gradleRunner()
.withArguments("spotlessCheck").build().getOutput();
Assertions.assertThat(oldestSupported.replace("\r", "")).startsWith(
":spotlessCheck UP-TO-DATE\n" +
":spotlessInternalRegisterDependencies\n" +
":sub:spotlessJava\n" +
":sub:spotlessJavaCheck\n" +
":sub:spotlessCheck\n" +
"\n" +
"BUILD SUCCESSFUL");
if (JreVersion.thisVm() == JreVersion._8) {
String oldestSupported = gradleRunner()
.withArguments("spotlessCheck").build().getOutput();
Assertions.assertThat(oldestSupported.replace("\r", "")).startsWith(
":spotlessCheck UP-TO-DATE\n" +
":spotlessInternalRegisterDependencies\n" +
":sub:spotlessJava\n" +
":sub:spotlessJavaCheck\n" +
":sub:spotlessCheck\n" +
"\n" +
"BUILD SUCCESSFUL");
}

setFile("gradle.properties").toLines();
String newestSupported = gradleRunner().withGradleVersion("6.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private void integration(String patterns,
GradleRunner runner = gradleRunner()
.withArguments("spotlessApply", "-PspotlessFiles=" + patterns);
if (isKotlin) {
runner.withGradleVersion("4.0");
runner.withGradleVersion(requestGradleForJre8and11("4.0"));
}
runner.build();

Expand Down
1 change: 1 addition & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [1.30.0] - 2020-04-10
### Added
* Support for prettier ([#555](https://github.com/diffplug/spotless/pull/555)).
* Support for google-java-format 1.8 (requires you to run build on Java 11) ([#562](https://github.com/diffplug/spotless/issues/562))

## [1.29.0] - 2020-04-02
### Added
Expand Down
Loading