diff --git a/changelog/@unreleased/pr-989.v2.yml b/changelog/@unreleased/pr-989.v2.yml new file mode 100644 index 000000000..484d1fa82 --- /dev/null +++ b/changelog/@unreleased/pr-989.v2.yml @@ -0,0 +1,7 @@ +type: improvement +improvement: + description: Load palantir-java-format dynamically from the same configuration set + up by `com.palantir-java-format` which is also used to determine the version used + by IntelliJ. + links: + - https://github.com/palantir/gradle-baseline/pull/989 diff --git a/gradle-baseline-java/build.gradle b/gradle-baseline-java/build.gradle index dfa77e96a..3b185d105 100644 --- a/gradle-baseline-java/build.gradle +++ b/gradle-baseline-java/build.gradle @@ -15,7 +15,7 @@ dependencies { compile 'net.ltgt.gradle:gradle-errorprone-plugin' compile 'org.apache.maven.shared:maven-dependency-analyzer' compile 'org.github.ngbinh.scalastyle:gradle-scalastyle-plugin_2.11' - implementation 'com.palantir.javaformat:palantir-java-format' + implementation 'com.palantir.javaformat:palantir-java-format-spi' implementation 'com.palantir.javaformat:gradle-palantir-java-format' testCompile gradleTestKit() diff --git a/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/Baseline.java b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/Baseline.java index 4fa2a0f62..734a31c3a 100644 --- a/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/Baseline.java +++ b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/Baseline.java @@ -37,9 +37,8 @@ public void apply(Project project) { rootProject.getPluginManager().apply(BaselineConfig.class); rootProject.getPluginManager().apply(BaselineCircleCi.class); if (BaselineFormat.palantirJavaFormatterEnabled(project)) { - // This plugin currently sets up IntelliJ but could set up eclipse too in the future, so it doesn't - // belong in BaselineIdea. - rootProject.getPluginManager().apply("com.palantir.java-format"); + rootProject.getPluginManager().apply("com.palantir.java-format-provider"); + rootProject.getPluginManager().apply("com.palantir.java-format-idea"); } rootProject.allprojects(proj -> { proj.getPluginManager().apply(BaselineCheckstyle.class); diff --git a/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/BaselineFormat.java b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/BaselineFormat.java index cebf0ea8c..3af9343ae 100644 --- a/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/BaselineFormat.java +++ b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/BaselineFormat.java @@ -17,10 +17,9 @@ package com.palantir.baseline.plugins; import com.diffplug.gradle.spotless.SpotlessExtension; -import com.diffplug.spotless.FormatterFunc; -import com.palantir.javaformat.java.Formatter; -import com.palantir.javaformat.java.JavaFormatterOptions; -import com.palantir.javaformat.java.JavaFormatterOptions.Style; +import com.google.common.base.Preconditions; +import com.palantir.baseline.plugins.format.PalantirJavaFormatStep; +import com.palantir.javaformat.gradle.JavaFormatExtension; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; @@ -52,11 +51,8 @@ public void apply(Project project) { spotlessExtension.java(java -> { // Configure a lazy FileCollection then pass it as the target ConfigurableFileCollection allJavaFiles = project.files(); - project - .getConvention() - .getPlugin(JavaPluginConvention.class) - .getSourceSets() - .all(sourceSet -> allJavaFiles.from( + project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().all( + sourceSet -> allJavaFiles.from( sourceSet.getAllJava().filter(file -> !file.toString().contains(GENERATED_MARKER)))); java.target(allJavaFiles); @@ -67,7 +63,10 @@ public void apply(Project project) { if (eclipseFormattingEnabled(project) && palantirJavaFormatterEnabled(project)) { throw new GradleException( "Can't use both eclipse and palantir-java-format at the same time, please delete one of " - + ECLIPSE_FORMATTING + " or " + PJF_PROPERTY + " from your gradle.properties"); + + ECLIPSE_FORMATTING + + " or " + + PJF_PROPERTY + + " from your gradle.properties"); } if (eclipseFormattingEnabled(project)) { @@ -75,7 +74,13 @@ public void apply(Project project) { } if (palantirJavaFormatterEnabled(project)) { - java.customLazy("palantir-java-format", PalantirJavaFormatterFunc::new); + Preconditions.checkState( + project.getRootProject().getPluginManager().hasPlugin("com.palantir.java-format-provider"), + "Must apply `com.palantir.baseline` to root project when setting '%s'", + PJF_PROPERTY); + java.addStep(PalantirJavaFormatStep.create( + project.getRootProject().getConfigurations().getByName("palantirJavaFormat"), + project.getRootProject().getExtensions().getByType(JavaFormatExtension.class))); } java.trimTrailingWhitespace(); @@ -99,7 +104,7 @@ public void apply(Project project) { }); project.getTasks().withType(JavaCompile.class).configureEach(spotlessJava::mustRunAfter); - //re-enable spotless checking, but lazily so it doesn't eagerly configure everything else + // re-enable spotless checking, but lazily so it doesn't eagerly configure everything else project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME).configure(t -> { t.dependsOn(project.getTasks().named("spotlessCheck")); }); @@ -118,14 +123,4 @@ static boolean palantirJavaFormatterEnabled(Project project) { static Path eclipseConfigFile(Project project) { return project.getRootDir().toPath().resolve(".baseline/spotless/eclipse.xml"); } - - private static class PalantirJavaFormatterFunc implements FormatterFunc { - private static final JavaFormatterOptions OPTIONS = - JavaFormatterOptions.builder().style(Style.PALANTIR).build(); - - @Override - public String apply(String input) throws Exception { - return Formatter.createFormatter(OPTIONS).formatSourceAndFixImports(input); - } - } } diff --git a/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/format/PalantirJavaFormatStep.java b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/format/PalantirJavaFormatStep.java new file mode 100644 index 000000000..b8591e1b7 --- /dev/null +++ b/gradle-baseline-java/src/main/groovy/com/palantir/baseline/plugins/format/PalantirJavaFormatStep.java @@ -0,0 +1,90 @@ +/* + * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. + * + * 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.palantir.baseline.plugins.format; + +import com.diffplug.spotless.FileSignature; +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.google.common.base.Suppliers; +import com.palantir.javaformat.gradle.JavaFormatExtension; +import com.palantir.javaformat.java.FormatterService; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.function.Supplier; +import org.gradle.api.artifacts.Configuration; + +public final class PalantirJavaFormatStep { + + private static final String IMPL_CLASS = "com.palantir.javaformat.java.Formatter"; + + private PalantirJavaFormatStep() {} + + private static final String NAME = "palantir-java-format"; + + /** Creates a step which formats everything - code, import order, and unused imports. */ + public static FormatterStep create(Configuration palantirJavaFormat, JavaFormatExtension extension) { + ensureImplementationNotDirectlyLoadable(); + Supplier memoizedService = Suppliers.memoize(extension::serviceLoad); + return FormatterStep.createLazy( + NAME, () -> new State(palantirJavaFormat.getFiles(), memoizedService), State::createFormat); + } + + static final class State implements Serializable { + private static final long serialVersionUID = 1L; + + // Kept for state serialization purposes. + @SuppressWarnings("unused") + private final String stepName = NAME; + + // Kept for state serialization purposes. + @SuppressWarnings({"unused", "FieldCanBeLocal"}) + private final FileSignature jarsSignature; + + // Transient as this is not serializable. + private final transient Supplier memoizedFormatter; + + /** + * Build a cacheable state for spotless from the given jars, that uses the given {@link FormatterService}. + * + * @param jars The jars that contain the palantir-java-format implementation. This is only used for caching and + * up-to-dateness purposes. + */ + State(Iterable jars, Supplier memoizedFormatter) throws IOException { + this.jarsSignature = FileSignature.signAsSet(jars); + this.memoizedFormatter = memoizedFormatter; + } + + @SuppressWarnings("NullableProblems") + FormatterFunc createFormat() { + return memoizedFormatter.get()::formatSourceReflowStringsAndFixImports; + } + } + + private static void ensureImplementationNotDirectlyLoadable() { + try { + PalantirJavaFormatStep.class.getClassLoader().loadClass(IMPL_CLASS); + } catch (ClassNotFoundException e) { + // expected + return; + } + throw new RuntimeException("Expected not be be able to load " + + IMPL_CLASS + + " via main class loader but was able to. Please ensure that `buildscript.configurations.classpath`" + + " doesn't depend on `com.palantir.javaformat:palantir-java-format`."); + } +} diff --git a/gradle-baseline-java/src/test/groovy/com/palantir/baseline/BaselineFormatIntegrationTest.groovy b/gradle-baseline-java/src/test/groovy/com/palantir/baseline/BaselineFormatIntegrationTest.groovy index 61f237e80..5703a4c47 100644 --- a/gradle-baseline-java/src/test/groovy/com/palantir/baseline/BaselineFormatIntegrationTest.groovy +++ b/gradle-baseline-java/src/test/groovy/com/palantir/baseline/BaselineFormatIntegrationTest.groovy @@ -119,8 +119,14 @@ class BaselineFormatIntegrationTest extends AbstractPluginTest { buildFile << """ plugins { id 'java' + id 'com.palantir.java-format' id 'com.palantir.baseline-format' } + repositories { + // to resolve the `palantirJavaFormat` configuration + maven { url 'https://dl.bintray.com/palantir/releases' } + jcenter() + } """.stripIndent() file('gradle.properties') << "com.palantir.baseline-format.palantir-java-format=true\n" diff --git a/gradle-baseline-java/src/test/resources/com/palantir/baseline/palantirjavaformat-expected/MultilineStringConstant.java b/gradle-baseline-java/src/test/resources/com/palantir/baseline/palantirjavaformat-expected/MultilineStringConstant.java index abab4bea4..8792cfbb2 100644 --- a/gradle-baseline-java/src/test/resources/com/palantir/baseline/palantirjavaformat-expected/MultilineStringConstant.java +++ b/gradle-baseline-java/src/test/resources/com/palantir/baseline/palantirjavaformat-expected/MultilineStringConstant.java @@ -3,15 +3,11 @@ class MultilineStringConstant { // NON-NLS comments are required for i18n, it's important they are kept with their strings. - private static final String MULTIPLE_LINE_NON_NLS = "field_0," - + //$NON-NLS-1$ - "field_1," - + //$NON-NLS-1$ - "field_2," - + //$NON-NLS-1$ - "field_3," - + //$NON-NLS-1$ - "field_4"; //$NON-NLS-1$ + private static final String MULTIPLE_LINE_NON_NLS = "field_0," //$NON-NLS-1$ + + "field_1," //$NON-NLS-1$ + + "field_2," //$NON-NLS-1$ + + "field_3," //$NON-NLS-1$ + + "field_4"; //$NON-NLS-1$ private static final String MULTIPLE_LINE_NO_COMMENT = "field_0," + "field_1," + "field_2," + "field_3," + "field_4"; diff --git a/versions.props b/versions.props index 02aac34fa..63c714e39 100644 --- a/versions.props +++ b/versions.props @@ -7,7 +7,7 @@ com.google.errorprone:error_prone_test_helpers = 2.3.3 com.google.guava:guava = 27.1-jre com.netflix.nebula:nebula-dependency-recommender = 9.0.0 com.palantir.configurationresolver:gradle-configuration-resolver-plugin = 0.4.0 -com.palantir.javaformat:* = 0.2.7 +com.palantir.javaformat:* = 0.3.0 com.palantir.safe-logging:* = 1.11.0 org.apache.maven.shared:maven-dependency-analyzer = 1.11.1 org.github.ngbinh.scalastyle:gradle-scalastyle-plugin_2.11 = 1.0.1