diff --git a/CHANGES.md b/CHANGES.md index 5b0e8c042a..7a90d0f039 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 +- Add support for Java formatting via [`prince-of-space`](https://github.com/agustafson/prince-of-space). ([#2991](https://github.com/diffplug/spotless/pull/2991)) ## [4.8.0] - 2026-06-29 ### Added diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b8807b1dd4..675cd3fa3c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -53,6 +53,7 @@ gson = "com.google.code.gson:gson:2.14.0" javaparser-symbol-solver-core = "com.github.javaparser:javaparser-symbol-solver-core:3.27.1" ktfmt = "com.facebook:ktfmt:0.63" palantir-java-format = "com.palantir.javaformat:palantir-java-format:1.1.0" +prince-of-space-core = "io.github.agustafson.princeofspace:prince-of-space-core:2.2.0" scalafmt-core = "org.scalameta:scalafmt-core_2.13:3.8.1" sortpom-sorter = "com.github.ekryd.sortpom:sortpom-sorter:4.0.0" tabletest-formatter-core = "org.tabletest:tabletest-formatter-core:1.1.1" diff --git a/lib/build.gradle b/lib/build.gradle index b4175b2cba..fbfddf163c 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -22,6 +22,7 @@ def NEEDS_GLUE = [ 'ktfmt', 'ktlint', 'palantirJavaFormat', + 'princeOfSpace', 'scalafmt', 'sortPom', 'tableTestFormatter', @@ -117,6 +118,8 @@ dependencies { compatKtLint1Dot0Dot0CompileAndTestOnly libs.slf4j.api // palantirJavaFormat palantirJavaFormatCompileOnly libs.palantir.java.format // this version needs to stay compilable against Java 8 for CI Job testNpm + // princeOfSpace + princeOfSpaceCompileOnly libs.prince.of.space.core // scalafmt scalafmtCompileOnly libs.scalafmt.core // sortPom diff --git a/lib/src/main/java/com/diffplug/spotless/java/PrinceOfSpaceStep.java b/lib/src/main/java/com/diffplug/spotless/java/PrinceOfSpaceStep.java new file mode 100644 index 0000000000..f007a1dd52 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/java/PrinceOfSpaceStep.java @@ -0,0 +1,159 @@ +/* + * Copyright 2026 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.java; + +import java.io.Serial; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.util.Objects; + +import javax.annotation.Nullable; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.JarState; +import com.diffplug.spotless.Jvm; +import com.diffplug.spotless.Provisioner; + +/** Wraps up prince-of-space as a FormatterStep. */ +public final class PrinceOfSpaceStep implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + private static final String NAME = "prince-of-space"; + public static final String MAVEN_COORDINATE = "io.github.agustafson.princeofspace:prince-of-space-core:"; + public static final String DEFAULT_VERSION = "2.2.0"; + + /** The jar that contains the formatter. */ + private final JarState.Promised jarState; + /** Version of the formatter jar. */ + private final String formatterVersion; + @Nullable private final Options options; + + private PrinceOfSpaceStep(JarState.Promised jarState, String formatterVersion, @Nullable Options options) { + this.jarState = jarState; + this.formatterVersion = formatterVersion; + this.options = options; + } + + /** Creates a step which formats Java source with prince-of-space's default options. */ + public static FormatterStep create(Provisioner provisioner) { + return create(defaultVersion(), provisioner); + } + + /** Creates a step which formats Java source with prince-of-space's default options. */ + public static FormatterStep create(String version, Provisioner provisioner) { + return create(version, provisioner, null); + } + + /** Creates a step which formats Java source with the given options. */ + public static FormatterStep create(String version, Provisioner provisioner, @Nullable Options options) { + Objects.requireNonNull(version, "version"); + Objects.requireNonNull(provisioner, "provisioner"); + return FormatterStep.create(NAME, + new PrinceOfSpaceStep(JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), version, options), + PrinceOfSpaceStep::equalityState, + State::createFormat); + } + + /** Get default formatter version */ + public static String defaultVersion() { + return DEFAULT_VERSION; + } + + private State equalityState() { + return new State(jarState.get(), formatterVersion, options); + } + + /** Mutable bag of the optional prince-of-space {@code FormatterConfig} knobs; unset (null) fields keep prince-of-space's own defaults. */ + public static class Options implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + @Nullable private String indentStyle; + @Nullable private Integer indentSize; + @Nullable private Integer lineLength; + @Nullable private String wrapStyle; + @Nullable private Boolean closingParenOnNewLine; + @Nullable private Boolean trailingCommas; + @Nullable private Integer javaLanguageLevel; + + public Options() {} + + public void setIndentStyle(String indentStyle) { + this.indentStyle = indentStyle; + } + + public void setIndentSize(int indentSize) { + this.indentSize = indentSize; + } + + public void setLineLength(int lineLength) { + this.lineLength = lineLength; + } + + public void setWrapStyle(String wrapStyle) { + this.wrapStyle = wrapStyle; + } + + public void setClosingParenOnNewLine(boolean closingParenOnNewLine) { + this.closingParenOnNewLine = closingParenOnNewLine; + } + + public void setTrailingCommas(boolean trailingCommas) { + this.trailingCommas = trailingCommas; + } + + public void setJavaLanguageLevel(int javaLanguageLevel) { + this.javaLanguageLevel = javaLanguageLevel; + } + } + + private static final class State implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + private final JarState jarState; + private final String formatterVersion; + @Nullable private final Options options; + + State(JarState jarState, String formatterVersion, @Nullable Options options) { + if (Jvm.version() < 17) { + throw new IllegalStateException("prince-of-space requires a JDK 17+ host runtime, this JVM is " + Jvm.version()); + } + this.jarState = jarState; + this.formatterVersion = formatterVersion; + this.options = options; + } + + FormatterFunc createFormat() throws Exception { + final ClassLoader classLoader = jarState.getClassLoader(); + final Class formatterFunc = classLoader.loadClass("com.diffplug.spotless.glue.pos.PrinceOfSpaceFormatterFunc"); + final Constructor constructor = formatterFunc.getConstructor( + String.class, Integer.class, Integer.class, String.class, Boolean.class, Boolean.class, Integer.class); + if (options == null) { + return (FormatterFunc) constructor.newInstance(null, null, null, null, null, null, null); + } + return (FormatterFunc) constructor.newInstance( + options.indentStyle, + options.indentSize, + options.lineLength, + options.wrapStyle, + options.closingParenOnNewLine, + options.trailingCommas, + options.javaLanguageLevel); + } + } +} diff --git a/lib/src/princeOfSpace/java/com/diffplug/spotless/glue/pos/PrinceOfSpaceFormatterFunc.java b/lib/src/princeOfSpace/java/com/diffplug/spotless/glue/pos/PrinceOfSpaceFormatterFunc.java new file mode 100644 index 0000000000..3018d5a276 --- /dev/null +++ b/lib/src/princeOfSpace/java/com/diffplug/spotless/glue/pos/PrinceOfSpaceFormatterFunc.java @@ -0,0 +1,68 @@ +/* + * Copyright 2026 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.pos; + +import java.io.File; + +import io.princeofspace.Formatter; +import io.princeofspace.model.FormatterConfig; +import io.princeofspace.model.IndentStyle; +import io.princeofspace.model.JavaLanguageLevel; +import io.princeofspace.model.WrapStyle; + +import com.diffplug.spotless.FormatterFunc; + +public class PrinceOfSpaceFormatterFunc implements FormatterFunc.NeedsFile { + + private final Formatter formatter; + + public PrinceOfSpaceFormatterFunc(String indentStyle, Integer indentSize, Integer lineLength, String wrapStyle, + Boolean closingParenOnNewLine, Boolean trailingCommas, Integer javaLanguageLevel) { + FormatterConfig.Builder builder = FormatterConfig.builder(); + if (indentStyle != null) { + builder.indentStyle(IndentStyle.valueOf(indentStyle)); + } + if (indentSize != null) { + builder.indentSize(indentSize); + } + if (lineLength != null) { + builder.lineLength(lineLength); + } + if (wrapStyle != null) { + builder.wrapStyle(WrapStyle.valueOf(wrapStyle)); + } + if (closingParenOnNewLine != null) { + builder.closingParenOnNewLine(closingParenOnNewLine); + } + if (trailingCommas != null) { + builder.trailingCommas(trailingCommas); + } + if (javaLanguageLevel != null) { + builder.javaLanguageLevel(JavaLanguageLevel.of(javaLanguageLevel)); + } + this.formatter = new Formatter(builder.build()); + } + + @Override + public String applyWithFile(String unix, File file) throws Exception { + return formatter.format(unix, file.toPath()); + } + + @Override + public String toString() { + return "PrinceOfSpaceFormatterFunc{formatter=" + formatter + '}'; + } +} diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 9665b4068c..ace90863ab 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,6 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] +### Added +- Add support for Java formatting via [`prince-of-space`](https://github.com/agustafson/prince-of-space) with the new `princeOfSpace()` step. ([#2991](https://github.com/diffplug/spotless/pull/2991)) ## [8.8.0] - 2026-06-29 ### Added diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 443acf7851..6df48c4b32 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -56,7 +56,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui - [Git hook (optional)](#git-hook) - [Linting](#linting) - **Languages** - - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea)) + - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [prince-of-space](#prince-of-space), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea)) - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier)) - [Scala](#scala) ([scalafmt](#scalafmt)) @@ -312,6 +312,24 @@ spotless { palantirJavaFormat('2.39.0').formatJavadoc(true) ``` +### prince-of-space + +[homepage](https://github.com/agustafson/prince-of-space). Requires a JDK 17+ host runtime. +```gradle +spotless { + java { + princeOfSpace() + // optional: configure any of the formatter's options + princeOfSpace('2.2.0') + .indentStyle('SPACES') // or 'TABS' + .indentSize(4) + .lineLength(120) + .wrapStyle('BALANCED') // or 'WIDE', 'NARROW' + .closingParenOnNewLine(true) + .trailingCommas(false) + .javaLanguageLevel(17) +``` + ### eclipse jdt [homepage](https://download.eclipse.org/eclipse/downloads/). See [here](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the config file mentioned below. diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java index 4ea13c261d..4bdbd5266d 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java @@ -46,6 +46,7 @@ import com.diffplug.spotless.java.GoogleJavaFormatStep; import com.diffplug.spotless.java.ImportOrderStep; import com.diffplug.spotless.java.PalantirJavaFormatStep; +import com.diffplug.spotless.java.PrinceOfSpaceStep; import com.diffplug.spotless.java.RemoveUnusedImportsStep; import com.diffplug.spotless.java.TableTestFormatterStep; @@ -308,6 +309,73 @@ private FormatterStep createStep() { } } + /** Uses the prince-of-space jar to format source code. */ + public PrinceOfSpaceConfig princeOfSpace() { + return princeOfSpace(PrinceOfSpaceStep.defaultVersion()); + } + + /** Uses the given version of prince-of-space to format source code. */ + public PrinceOfSpaceConfig princeOfSpace(String version) { + Objects.requireNonNull(version); + return new PrinceOfSpaceConfig(version); + } + + public class PrinceOfSpaceConfig { + final String version; + final PrinceOfSpaceStep.Options options = new PrinceOfSpaceStep.Options(); + + PrinceOfSpaceConfig(String version) { + this.version = Objects.requireNonNull(version); + addStep(createStep()); + } + + public PrinceOfSpaceConfig indentStyle(String indentStyle) { + options.setIndentStyle(indentStyle); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig indentSize(int indentSize) { + options.setIndentSize(indentSize); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig lineLength(int lineLength) { + options.setLineLength(lineLength); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig wrapStyle(String wrapStyle) { + options.setWrapStyle(wrapStyle); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig closingParenOnNewLine(boolean closingParenOnNewLine) { + options.setClosingParenOnNewLine(closingParenOnNewLine); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig trailingCommas(boolean trailingCommas) { + options.setTrailingCommas(trailingCommas); + replaceStep(createStep()); + return this; + } + + public PrinceOfSpaceConfig javaLanguageLevel(int javaLanguageLevel) { + options.setJavaLanguageLevel(javaLanguageLevel); + replaceStep(createStep()); + return this; + } + + private FormatterStep createStep() { + return PrinceOfSpaceStep.create(version, provisioner(), options); + } + } + public EclipseConfig eclipse() { return eclipse(EclipseJdtFormatterStep.defaultVersion()); } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index f2a4a75566..80b240eae7 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,6 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +- Add support for Java formatting via [`prince-of-space`](https://github.com/agustafson/prince-of-space) with the new `` step. ([#2991](https://github.com/diffplug/spotless/pull/2991)) ## [3.8.0] - 2026-06-29 ### Added diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 1d0bf6d25f..47e9c885c0 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -40,7 +40,7 @@ user@machine repo % mvn spotless:check - [Git hook (optional)](#git-hook) - [Binding to maven phase](#binding-to-maven-phase) - **Languages** - - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea)) + - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [prince-of-space](#prince-of-space), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea)) - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier)) - [Scala](#scala) ([scalafmt](#scalafmt)) @@ -293,6 +293,23 @@ any other maven phase (i.e. compile) then it can be configured as below; ``` +### prince-of-space + +[homepage](https://github.com/agustafson/prince-of-space). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/PrinceOfSpace.java). Requires a JDK 17+ host runtime. + +```xml + + 2.2.0 + SPACES + 4 + 120 + BALANCED + true + false + 17 + +``` + ### eclipse jdt [homepage](https://download.eclipse.org/eclipse/downloads/). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java). See [here](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the config file mentioned below. diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java index fe6e2633ac..9e31078eea 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java @@ -71,6 +71,10 @@ public void addPalantirJavaFormat(PalantirJavaFormat palantirJavaFormat) { addStepFactory(palantirJavaFormat); } + public void addPrinceOfSpace(PrinceOfSpace princeOfSpace) { + addStepFactory(princeOfSpace); + } + public void addRemoveUnusedImports(RemoveUnusedImports removeUnusedImports) { addStepFactory(removeUnusedImports); } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/PrinceOfSpace.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/PrinceOfSpace.java new file mode 100644 index 0000000000..a862330ad7 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/PrinceOfSpace.java @@ -0,0 +1,78 @@ +/* + * Copyright 2026 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.maven.java; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.PrinceOfSpaceStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class PrinceOfSpace implements FormatterStepFactory { + + @Parameter + private String version; + + @Parameter + private String indentStyle; + + @Parameter + private Integer indentSize; + + @Parameter + private Integer lineLength; + + @Parameter + private String wrapStyle; + + @Parameter + private Boolean closingParenOnNewLine; + + @Parameter + private Boolean trailingCommas; + + @Parameter + private Integer javaLanguageLevel; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + String version = this.version != null ? this.version : PrinceOfSpaceStep.defaultVersion(); + PrinceOfSpaceStep.Options options = new PrinceOfSpaceStep.Options(); + if (indentStyle != null) { + options.setIndentStyle(indentStyle); + } + if (indentSize != null) { + options.setIndentSize(indentSize); + } + if (lineLength != null) { + options.setLineLength(lineLength); + } + if (wrapStyle != null) { + options.setWrapStyle(wrapStyle); + } + if (closingParenOnNewLine != null) { + options.setClosingParenOnNewLine(closingParenOnNewLine); + } + if (trailingCommas != null) { + options.setTrailingCommas(trailingCommas); + } + if (javaLanguageLevel != null) { + options.setJavaLanguageLevel(javaLanguageLevel); + } + return PrinceOfSpaceStep.create(version, config.getProvisioner(), options); + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/java/PrinceOfSpaceStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/PrinceOfSpaceStepTest.java new file mode 100644 index 0000000000..853f2e4bee --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/java/PrinceOfSpaceStepTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2026 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.java; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.Collections; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.Formatter; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.SerializableEqualityTester; +import com.diffplug.spotless.TestProvisioner; + +class PrinceOfSpaceStepTest extends ResourceHarness { + + private static String format(FormatterStep step, String input) { + try (Formatter formatter = Formatter.builder() + .steps(Collections.singletonList(step)) + .lineEndingsPolicy(LineEnding.UNIX.createPolicy()) + .encoding(StandardCharsets.UTF_8) + .build()) { + return formatter.compute(LineEnding.toUnix(input), new File("")); + } + } + + @Test + void behavior() throws Exception { + FormatterStep step = PrinceOfSpaceStep.create(TestProvisioner.mavenCentral()); + String input = "class T { void m() { int x=1;} }"; + String formatted = format(step, input); + assertThat(formatted).contains("int x = 1;"); + assertThat(format(step, formatted)).isEqualTo(formatted); + } + + @Test + void behaviorWithOptions() throws Exception { + PrinceOfSpaceStep.Options options = new PrinceOfSpaceStep.Options(); + options.setIndentSize(2); + FormatterStep step = PrinceOfSpaceStep.create(PrinceOfSpaceStep.defaultVersion(), TestProvisioner.mavenCentral(), options); + String input = "class T { void m() { int x=1;} }"; + String formatted = format(step, input); + assertThat(formatted).contains("int x = 1;").contains("\n "); + assertThat(format(step, formatted)).isEqualTo(formatted); + } + + @Test + void equality() { + new SerializableEqualityTester() { + String version = PrinceOfSpaceStep.defaultVersion(); + Integer indentSize; + + @Override + protected void setupTest(API api) { + // same version == same + api.areDifferentThan(); + + // change the version, and it's different + version = "2.1.1"; + api.areDifferentThan(); + version = PrinceOfSpaceStep.defaultVersion(); + + // change the options, and it's different + indentSize = 4; + api.areDifferentThan(); + indentSize = null; + } + + @Override + protected FormatterStep create() { + PrinceOfSpaceStep.Options options; + if (indentSize == null) { + options = null; + } else { + options = new PrinceOfSpaceStep.Options(); + options.setIndentSize(indentSize); + } + return PrinceOfSpaceStep.create(version, TestProvisioner.mavenCentral(), options); + } + }.testEquals(); + } +}