Skip to content

Commit

Permalink
Simplify the PJF step using a compileOnly dependency
Browse files Browse the repository at this point in the history
Support for non-default styles and alternative artifacts have
been dropped in favor simplicity.
If requested, we can add support for reflowing strings in the
future.
  • Loading branch information
carterkozak committed Jan 11, 2022
1 parent e9352f6 commit 0d83dca
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 195 deletions.
3 changes: 3 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ apply from: rootProject.file('gradle/java-publish.gradle')

def NEEDS_GLUE = [
'sortPom',
'palantirJavaFormat',
'ktlint',
'flexmark'
]
Expand All @@ -29,6 +30,8 @@ dependencies {
// used for pom sorting
sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0'

palantirJavaFormatCompileOnly 'com.palantir.javaformat:palantir-java-format:1.1.0'

String VER_KTLINT='0.43.2'
ktlintCompileOnly "com.pinterest:ktlint:$VER_KTLINT"
ktlintCompileOnly "com.pinterest.ktlint:ktlint-core:$VER_KTLINT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,20 @@
package com.diffplug.spotless.java;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.Objects;

import com.diffplug.spotless.*;
import com.diffplug.spotless.ThrowingEx.Function;

/** Wraps up <a href="https://github.com/palantir/palantir-java-format">palantir-java-format</a> fork of
* <a href="https://github.com/google/google-java-format">google-java-format</a> as a FormatterStep. */
public class PalantirJavaFormatStep {
// prevent direct instantiation
private PalantirJavaFormatStep() {}

private static final String DEFAULT_STYLE = "PALANTIR";
static final String NAME = "palantir-java-format";
static final String MAVEN_COORDINATE = "com.palantir.javaformat:palantir-java-format";
static final String FORMATTER_CLASS = "com.palantir.javaformat.java.Formatter";
static final String FORMATTER_METHOD = "formatSource";

private static final String OPTIONS_CLASS = "com.palantir.javaformat.java.JavaFormatterOptions";
private static final String OPTIONS_BUILDER_METHOD = "builder";
private static final String OPTIONS_BUILDER_CLASS = "com.palantir.javaformat.java.JavaFormatterOptions$Builder";
private static final String OPTIONS_BUILDER_STYLE_METHOD = "style";
private static final String OPTIONS_BUILDER_BUILD_METHOD = "build";
private static final String OPTIONS_STYLE = "com.palantir.javaformat.java.JavaFormatterOptions$Style";

private static final String REMOVE_UNUSED_CLASS = "com.palantir.javaformat.java.RemoveUnusedImports";
private static final String REMOVE_UNUSED_METHOD = "removeUnusedImports";

private static final String IMPORT_ORDERER_CLASS = "com.palantir.javaformat.java.ImportOrderer";
private static final String IMPORT_ORDERER_METHOD = "reorderImports";
private static final String NAME = "palantir-java-format";
private static final String MAVEN_COORDINATE = "com.palantir.javaformat:palantir-java-format:";
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(8, "1.1.0").add(11, "2.10.0");

/** Creates a step which formats everything - code, import order, and unused imports. */
public static FormatterStep create(Provisioner provisioner) {
Expand All @@ -54,99 +38,37 @@ public static FormatterStep create(Provisioner provisioner) {

/** Creates a step which formats everything - code, import order, and unused imports. */
public static FormatterStep create(String version, Provisioner provisioner) {
return create(version, DEFAULT_STYLE, provisioner);
}

/** Creates a step which formats everything - code, import order, and unused imports. */
public static FormatterStep create(String version, String style, Provisioner provisioner) {
return create(MAVEN_COORDINATE, version, style, provisioner);
}

/** Creates a step which formats everything - groupArtifact, code, import order, and unused imports. */
public static FormatterStep create(String groupArtifact, String version, String style, Provisioner provisioner) {
Objects.requireNonNull(groupArtifact, "groupArtifact");
if (groupArtifact.chars().filter(ch -> ch == ':').count() != 1) {
throw new IllegalArgumentException("groupArtifact must be in the form 'groupId:artifactId'");
}
Objects.requireNonNull(version, "version");
Objects.requireNonNull(style, "style");
Objects.requireNonNull(provisioner, "provisioner");

return FormatterStep.createLazy(NAME,
() -> new State(NAME, groupArtifact, version, style, provisioner),
() -> new State(JarState.from(MAVEN_COORDINATE + version, provisioner), version),
State::createFormat);
}

static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(8, "1.1.0").add(11, "2.10.0");

public static String defaultGroupArtifact() {
return MAVEN_COORDINATE;
}

/** Get default formatter version */
public static String defaultVersion() {
return JVM_SUPPORT.getRecommendedFormatterVersion();
}

public static String defaultStyle() {
return DEFAULT_STYLE;
}

static final class State implements Serializable {
private static final class State implements Serializable {
private static final long serialVersionUID = 1L;

/** The jar that contains the formatter. */
final JarState jarState;
final String stepName;
final String version;
final String style;
private final JarState jarState;
/** Version of the formatter jar. */
private final String formatterVersion;

State(String stepName, String groupArtifact, String version, String style, Provisioner provisioner) throws Exception {
JVM_SUPPORT.assertFormatterSupported(version);
this.jarState = JarState.from(groupArtifact + ":" + version, provisioner);
this.stepName = stepName;
this.version = version;
this.style = style;
State(JarState jarState, String formatterVersion) {
this.jarState = jarState;
this.formatterVersion = formatterVersion;
}

@SuppressWarnings({"unchecked", "rawtypes"})
FormatterFunc createFormat() throws Exception {
ClassLoader classLoader = jarState.getClassLoader();

// instantiate the formatter and get its format method
Class<?> optionsClass = classLoader.loadClass(OPTIONS_CLASS);
Class<?> optionsBuilderClass = classLoader.loadClass(OPTIONS_BUILDER_CLASS);
Method optionsBuilderMethod = optionsClass.getMethod(OPTIONS_BUILDER_METHOD);
Object optionsBuilder = optionsBuilderMethod.invoke(null);

Class<?> optionsStyleClass = classLoader.loadClass(OPTIONS_STYLE);
Object styleConstant = Enum.valueOf((Class<Enum>) optionsStyleClass, style);
Method optionsBuilderStyleMethod = optionsBuilderClass.getMethod(OPTIONS_BUILDER_STYLE_METHOD, optionsStyleClass);
optionsBuilderStyleMethod.invoke(optionsBuilder, styleConstant);

Method optionsBuilderBuildMethod = optionsBuilderClass.getMethod(OPTIONS_BUILDER_BUILD_METHOD);
Object options = optionsBuilderBuildMethod.invoke(optionsBuilder);

Class<?> formatterClazz = classLoader.loadClass(FORMATTER_CLASS);
Object formatter = formatterClazz.getMethod("createFormatter", optionsClass).invoke(null, options);
Method formatterMethod = formatterClazz.getMethod(FORMATTER_METHOD, String.class);

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

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

return JVM_SUPPORT.suggestLaterVersionOnError(version, (input -> {
String formatted = (String) formatterMethod.invoke(formatter, input);
String removedUnused = removeUnused.apply(formatted);
return (String) importOrdererMethod.invoke(null, removedUnused);
}));
}

private static Function<String, String> constructRemoveUnusedFunction(ClassLoader classLoader)
throws NoSuchMethodException, ClassNotFoundException {
Class<?> removeUnusedClass = classLoader.loadClass(REMOVE_UNUSED_CLASS);
Method removeUnusedMethod = removeUnusedClass.getMethod(REMOVE_UNUSED_METHOD, String.class);
return (x) -> (String) removeUnusedMethod.invoke(null, x);
final ClassLoader classLoader = jarState.getClassLoader();
final Class<?> formatterFunc = classLoader.loadClass("com.diffplug.spotless.glue.pjf.PalantirJavaFormatFormatterFunc");
final Constructor<?> constructor = formatterFunc.getConstructor();
return JVM_SUPPORT.suggestLaterVersionOnError(formatterVersion, (FormatterFunc) constructor.newInstance());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2022 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.spotless.glue.pjf;

import com.palantir.javaformat.java.Formatter;
import com.palantir.javaformat.java.ImportOrderer;
import com.palantir.javaformat.java.JavaFormatterOptions;
import com.palantir.javaformat.java.RemoveUnusedImports;

import com.diffplug.spotless.FormatterFunc;

public class PalantirJavaFormatFormatterFunc implements FormatterFunc {

private final Formatter formatter;

public PalantirJavaFormatFormatterFunc() {
formatter = Formatter.createFormatter(JavaFormatterOptions.builder()
.style(JavaFormatterOptions.Style.PALANTIR)
.build());
}

@Override
public String apply(String input) throws Exception {
String source = input;
source = ImportOrderer.reorderImports(source, JavaFormatterOptions.Style.PALANTIR);
source = RemoveUnusedImports.removeUnusedImports(source);
return formatter.formatSource(source);
}

@Override
public String toString() {
return "PalantirJavaFormatFormatterFunc{formatter=" + formatter + '}';
}
}
5 changes: 2 additions & 3 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,8 @@ This is a workaround to a [pending issue](https://github.com/diffplug/spotless/i
spotless {
java {
palantirJavaFormat()
// optional: you can specify a specific version and/or switch to GOOGLE/AOSP style
// and/or use custom group artifact (you probably don't need this)
palantirJavaFormat('2.9.0').style("PALANTIR").groupArtifact('com.google.googlejavaformat:google-java-format')
// optional: you can specify a specific version
palantirJavaFormat('2.9.0')
```

**⚠️ Note on using Palantir Java Format with Java 16+**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,34 +194,14 @@ public PalantirJavaFormatConfig palantirJavaFormat(String version) {

public class PalantirJavaFormatConfig {
final String version;
String groupArtifact;
String style;

PalantirJavaFormatConfig(String version) {
this.version = Objects.requireNonNull(version);
this.groupArtifact = PalantirJavaFormatStep.defaultGroupArtifact();
this.style = PalantirJavaFormatStep.defaultStyle();
addStep(createStep());
}

public PalantirJavaFormatConfig groupArtifact(String groupArtifact) {
this.groupArtifact = Objects.requireNonNull(groupArtifact);
replaceStep(createStep());
return this;
}

public PalantirJavaFormatConfig style(String style) {
this.style = Objects.requireNonNull(style);
replaceStep(createStep());
return this;
}

private FormatterStep createStep() {
return PalantirJavaFormatStep.create(
groupArtifact,
version,
style,
provisioner());
return PalantirJavaFormatStep.create(version, provisioner());
}
}

Expand Down
3 changes: 0 additions & 3 deletions plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,6 @@ This is a workaround to a [pending issue](https://github.com/diffplug/spotless/i
```xml
<palantirJavaFormat>
<version>2.10.0</version> <!-- optional -->
<style>PALANTIR</style> <!-- or AOSP/GOOGLE (optional) -->
<!-- optional: custom group artifact (you probably don't need this) -->
<groupArtifact>com.palantir.javaformat:palantir-java-format</groupArtifact>
</palantirJavaFormat>
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,13 @@
import com.diffplug.spotless.maven.FormatterStepFactory;

public class PalantirJavaFormat implements FormatterStepFactory {
@Parameter
private String groupArtifact;

@Parameter
private String version;

@Parameter
private String style;

@Override
public FormatterStep newFormatterStep(FormatterStepConfig config) {
String groupArtifact = this.groupArtifact != null ? this.groupArtifact : PalantirJavaFormatStep.defaultGroupArtifact();
String version = this.version != null ? this.version : PalantirJavaFormatStep.defaultVersion();
String style = this.style != null ? this.style : PalantirJavaFormatStep.defaultStyle();
return PalantirJavaFormatStep.create(groupArtifact, version, style, config.getProvisioner());
return PalantirJavaFormatStep.create(version, config.getProvisioner());
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void jvm13Features() throws Exception {
}

@Test
@EnabledForJreRange(min = JAVA_11) // google-java-format requires JRE 11+
@EnabledForJreRange(min = JAVA_11)
void behavior2() throws Exception {
FormatterStep step = PalantirJavaFormatStep.create("2.10.0", TestProvisioner.mavenCentral());
StepHarness.forStep(step)
Expand All @@ -57,28 +57,9 @@ void behavior() throws Exception {
}

@Test
void behaviorWithAospStyle() throws Exception {
FormatterStep step = PalantirJavaFormatStep.create("1.1.0", "AOSP", TestProvisioner.mavenCentral());
StepHarness.forStep(step)
.testResource("java/palantirjavaformat/JavaCodeUnformatted.test", "java/palantirjavaformat/JavaCodeFormattedAOSP.test")
.testResource("java/palantirjavaformat/JavaCodeWithLicenseUnformatted.test", "java/palantirjavaformat/JavaCodeWithLicenseFormattedAOSP.test")
.testResource("java/palantirjavaformat/JavaCodeWithPackageUnformatted.test", "java/palantirjavaformat/JavaCodeWithPackageFormattedAOSP.test");
}

@Test
void behaviorWithCustomGroupArtifact() throws Exception {
FormatterStep step = PalantirJavaFormatStep.create(PalantirJavaFormatStep.defaultGroupArtifact(), "1.1.0", PalantirJavaFormatStep.defaultStyle(), TestProvisioner.mavenCentral());
StepHarness.forStep(step)
.testResource("java/palantirjavaformat/JavaCodeUnformatted.test", "java/palantirjavaformat/JavaCodeFormatted.test")
.testResource("java/palantirjavaformat/JavaCodeWithLicenseUnformatted.test", "java/palantirjavaformat/JavaCodeWithLicenseFormatted.test")
.testResource("java/palantirjavaformat/JavaCodeWithPackageUnformatted.test", "java/palantirjavaformat/JavaCodeWithPackageFormatted.test");
}

@Test
void equality() throws Exception {
void equality() {
new SerializableEqualityTester() {
String version = "1.1.0";
String style = "";

@Override
protected void setupTest(API api) {
Expand All @@ -87,15 +68,12 @@ protected void setupTest(API api) {
// change the version, and it's different
version = "1.0.0";
api.areDifferentThan();
// change the style, and it's different
style = "AOSP";
api.areDifferentThan();
}

@Override
protected FormatterStep create() {
String finalVersion = this.version;
return PalantirJavaFormatStep.create(finalVersion, style, TestProvisioner.mavenCentral());
return PalantirJavaFormatStep.create(finalVersion, TestProvisioner.mavenCentral());
}
}.testEquals();
}
Expand Down

0 comments on commit 0d83dca

Please sign in to comment.