diff --git a/CHANGES.md b/CHANGES.md index 94d69df336..04722f1c2b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Made ShadowCopy (`npmInstallCache`) more robust by re-creating the cache dir if it goes missing ([#1984](https://github.com/diffplug/spotless/issues/1984),[2096](https://github.com/diffplug/spotless/pull/2096)) * scalafmt.conf fileOverride section now works correctly ([#1854](https://github.com/diffplug/spotless/pull/1854)) ### Changes +* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) * Bump default `gherkin-utils` version to latest `8.0.2` -> `9.0.0`. ([#1703](https://github.com/diffplug/spotless/pull/1703)) * Bump default `google-java-format` version to latest `1.19.2` -> `1.22.0`. ([#2129](https://github.com/diffplug/spotless/pull/2129)) * Bump default `jackson` version to latest `2.14.2` -> `2.17.1`. ([#1685](https://github.com/diffplug/spotless/pull/1685)) @@ -28,8 +29,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `shfmt` version to latest `3.7.0` -> `3.8.0`. ([#2050](https://github.com/diffplug/spotless/pull/2050)) * Bump default `sortpom` version to latest `3.2.1` -> `4.0.0`. ([#2049](https://github.com/diffplug/spotless/pull/2049), [#2078](https://github.com/diffplug/spotless/pull/2078), [#2115](https://github.com/diffplug/spotless/pull/2115)) * Bump default `zjsonpatch` version to latest `0.4.14` -> `0.4.16`. ([#1969](https://github.com/diffplug/spotless/pull/1969)) -* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) ### Removed +* **BREAKING** Remove `FormatterStep.createNeverUpToDate` methods, they are available only in `testlib`. ([#2145](https://github.com/diffplug/spotless/pull/2145)) * **BREAKING** Remove `JarState.getMavenCoordinate(String prefix)`. ([#1945](https://github.com/diffplug/spotless/pull/1945)) * **BREAKING** Replace `PipeStepPair` with `FenceStep`. ([#1954](https://github.com/diffplug/spotless/pull/1954)) * **BREAKING** Fully removed `Rome`, use `Biome` instead. ([#2119](https://github.com/diffplug/spotless/pull/2119)) diff --git a/lib/src/main/java/com/diffplug/spotless/FormatterStep.java b/lib/src/main/java/com/diffplug/spotless/FormatterStep.java index 070e502a0c..5974151fba 100644 --- a/lib/src/main/java/com/diffplug/spotless/FormatterStep.java +++ b/lib/src/main/java/com/diffplug/spotless/FormatterStep.java @@ -172,34 +172,4 @@ static FormatterStep create( Objects.requireNonNull(state, "state"); return createLazy(name, () -> state, stateToFormatter); } - - /** - * @param name - * The name of the formatter step - * @param functionSupplier - * A supplier which will lazily generate the function - * used by the formatter step - * @return A FormatterStep which will never report that it is up-to-date, because - * it is not equal to the serialized representation of itself. - */ - static FormatterStep createNeverUpToDateLazy( - String name, - ThrowingEx.Supplier functionSupplier) { - return new FormatterStepImpl.NeverUpToDate(name, functionSupplier); - } - - /** - * @param name - * The name of the formatter step - * @param function - * The function used by the formatter step - * @return A FormatterStep which will never report that it is up-to-date, because - * it is not equal to the serialized representation of itself. - */ - static FormatterStep createNeverUpToDate( - String name, - FormatterFunc function) { - Objects.requireNonNull(function, "function"); - return createNeverUpToDateLazy(name, () -> function); - } } diff --git a/lib/src/main/java/com/diffplug/spotless/SerializedFunction.java b/lib/src/main/java/com/diffplug/spotless/SerializedFunction.java index d4d36edfb4..7cadb120d6 100644 --- a/lib/src/main/java/com/diffplug/spotless/SerializedFunction.java +++ b/lib/src/main/java/com/diffplug/spotless/SerializedFunction.java @@ -22,4 +22,22 @@ public interface SerializedFunction extends Serializable, ThrowingEx.Funct static SerializedFunction identity() { return t -> t; } + + static SerializedFunction alwaysReturns(R value) { + return new AlwaysReturns(value); + } + + class AlwaysReturns implements SerializedFunction { + private static final long serialVersionUID = 1L; + private final R value; + + AlwaysReturns(R value) { + this.value = value; + } + + @Override + public R apply(T t) { + return value; + } + } } diff --git a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java index 6d04c25962..941c1c376f 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.OnMatch; import com.diffplug.spotless.SerializableFileFilter; +import com.diffplug.spotless.SerializedFunction; import com.diffplug.spotless.ThrowingEx; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -119,15 +120,22 @@ public LicenseHeaderStep withSkipLinesMatching(@Nullable String skipLinesMatchin return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } - public FormatterStep build() { - FormatterStep formatterStep = null; + private static class SetLicenseHeaderYearsFromGitHistory implements SerializedFunction { + private static final long serialVersionUID = 1L; + @Override + public FormatterFunc apply(Runtime input) throws Exception { + return FormatterFunc.needsFile(input::setLicenseHeaderYearsFromGitHistory); + } + } + + public FormatterStep build() { + FormatterStep formatterStep; if (yearMode.get() == YearMode.SET_FROM_GIT) { - formatterStep = FormatterStep.createNeverUpToDateLazy(name, () -> { + formatterStep = FormatterStep.createLazy(name, () -> { boolean updateYear = false; // doesn't matter - Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching); - return FormatterFunc.needsFile(runtime::setLicenseHeaderYearsFromGitHistory); - }); + return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching); + }, new SetLicenseHeaderYearsFromGitHistory()); } else { formatterStep = FormatterStep.createLazy(name, () -> { // by default, we should update the year if the user is using ratchetFrom @@ -146,11 +154,9 @@ public FormatterStep build() { return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching); }, step -> FormatterFunc.needsFile(step::format)); } - if (contentPattern == null) { return formatterStep; } - return formatterStep.filterByContent(OnMatch.INCLUDE, contentPattern); } diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index d00a5f89e0..666221af89 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -14,6 +14,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Made ShadowCopy (`npmInstallCache`) more robust by re-creating the cache dir if it goes missing ([#1984](https://github.com/diffplug/spotless/issues/1984),[2096](https://github.com/diffplug/spotless/pull/2096)) * scalafmt.conf fileOverride section now works correctly ([#1854](https://github.com/diffplug/spotless/pull/1854)) ### Changes +* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) * Bump default `gherkin-utils` version to latest `8.0.2` -> `9.0.0`. ([#1703](https://github.com/diffplug/spotless/pull/1703)) * Bump default `google-java-format` version to latest `1.19.2` -> `1.22.0`. ([#2129](https://github.com/diffplug/spotless/pull/2129)) * Bump default `jackson` version to latest `2.14.2` -> `2.17.1`. ([#1685](https://github.com/diffplug/spotless/pull/1685)) @@ -23,7 +24,6 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `shfmt` version to latest `3.7.0` -> `3.8.0`. ([#2050](https://github.com/diffplug/spotless/pull/2050)) * Bump default `sortpom` version to latest `3.2.1` -> `4.0.0`. ([#2049](https://github.com/diffplug/spotless/pull/2049), [#2078](https://github.com/diffplug/spotless/pull/2078), [#2115](https://github.com/diffplug/spotless/pull/2115)) * Bump default `zjsonpatch` version to latest `0.4.14` -> `0.4.16`. ([#1969](https://github.com/diffplug/spotless/pull/1969)) -* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) ### Removed * **BREAKING** Fully removed `Rome`, use `Biome` instead. ([#2119](https://github.com/diffplug/spotless/pull/2119)) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 94e5298b66..6d8d85e2f4 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -53,6 +53,7 @@ import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.OnMatch; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.SerializedFunction; import com.diffplug.spotless.biome.BiomeFlavor; import com.diffplug.spotless.cpp.ClangFormatStep; import com.diffplug.spotless.extra.EclipseBasedStepBuilder; @@ -427,7 +428,21 @@ protected Integer calculateState() throws Exception { */ public void custom(String name, Closure formatter) { requireNonNull(formatter, "formatter"); - custom(name, formatter::call); + Closure dehydrated = formatter.dehydrate(); + custom(name, new ClosureFormatterFunc(dehydrated)); + } + + static class ClosureFormatterFunc implements FormatterFunc, Serializable { + private final Closure closure; + + ClosureFormatterFunc(Closure closure) { + this.closure = closure; + } + + @Override + public String apply(String unixNewlines) { + return closure.call(unixNewlines); + } } /** @@ -436,7 +451,7 @@ public void custom(String name, Closure formatter) { */ public void custom(String name, FormatterFunc formatter) { requireNonNull(formatter, "formatter"); - addStep(FormatterStep.createLazy(name, () -> globalState, unusedState -> formatter)); + addStep(FormatterStep.createLazy(name, () -> globalState, SerializedFunction.alwaysReturns(formatter))); } /** Highly efficient find-replace char sequence. */ diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java index af724ab961..24b2a8504d 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java @@ -21,7 +21,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.regex.Pattern; import org.assertj.core.api.Assertions; import org.gradle.api.Project; @@ -31,11 +30,11 @@ import com.diffplug.common.base.StringPrinter; import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.ResourceHarness; import com.diffplug.spotless.TestProvisioner; import com.diffplug.spotless.extra.integration.DiffMessageFormatter; +import com.diffplug.spotless.generic.TrimTrailingWhitespaceStep; class DiffMessageFormatterTest extends ResourceHarness { @@ -151,10 +150,7 @@ void customRunToFixMessage() throws Exception { @Test void whitespaceProblem() throws Exception { Bundle spotless = create(setFile("testFile").toContent("A \nB\t\nC \n")); - spotless.task.setSteps(List.of(FormatterStep.createNeverUpToDate("trimTrailing", input -> { - Pattern pattern = Pattern.compile("[ \t]+$", Pattern.UNIX_LINES | Pattern.MULTILINE); - return pattern.matcher(input).replaceAll(""); - }))); + spotless.task.setSteps(List.of(TrimTrailingWhitespaceStep.create())); assertCheckFailure(spotless, " testFile", " @@ -1,3 +1,3 @@", diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java index 92f6818f3e..99509d51a4 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/FormatTaskTest.java @@ -24,10 +24,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.ResourceHarness; import com.diffplug.spotless.TestProvisioner; +import com.diffplug.spotless.generic.ReplaceStep; class FormatTaskTest extends ResourceHarness { private SpotlessTaskImpl spotlessTask; @@ -62,7 +62,7 @@ void testStep() throws Exception { File outputFile = new File(spotlessTask.getOutputDirectory(), "testFile"); spotlessTask.setTarget(Collections.singleton(testFile)); - spotlessTask.setSteps(List.of(FormatterStep.createNeverUpToDate("double-p", content -> content.replace("pp", "p")))); + spotlessTask.setSteps(List.of(ReplaceStep.create("double-p", "pp", "p"))); Tasks.execute(spotlessTask); assertFile(outputFile).hasContent("aple"); diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PaddedCellTaskTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PaddedCellTaskTest.java index 7dc5581f5b..5d68db2492 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PaddedCellTaskTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PaddedCellTaskTest.java @@ -31,10 +31,11 @@ import com.diffplug.common.base.StringPrinter; import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.NeverUpToDateStep; import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.SerializedFunction; import com.diffplug.spotless.TestProvisioner; class PaddedCellTaskTest extends ResourceHarness { @@ -53,10 +54,10 @@ public BuildServiceParameters.None getParameters() { SpotlessCheck check; SpotlessApply apply; - Bundle(String name, FormatterFunc function) throws IOException { + Bundle(String name, SerializedFunction function) throws IOException { this.name = name; file = setFile("src/test." + name).toContent("CCC"); - FormatterStep step = FormatterStep.createNeverUpToDate(name, function); + FormatterStep step = NeverUpToDateStep.create(name, function); source = createFormatTask(name, step); check = createCheckTask(name, source); apply = createApplyTask(name, source); diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 2ee226208b..f3ba81d5bd 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Made ShadowCopy (`npmInstallCache`) more robust by re-creating the cache dir if it goes missing ([#1984](https://github.com/diffplug/spotless/issues/1984),[2096](https://github.com/diffplug/spotless/pull/2096)) * scalafmt.conf fileOverride section now works correctly ([#1854](https://github.com/diffplug/spotless/pull/1854)) ### Changes +* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) * Bump default `gherkin-utils` version to latest `8.0.2` -> `9.0.0`. ([#1703](https://github.com/diffplug/spotless/pull/1703)) * Bump default `google-java-format` version to latest `1.19.2` -> `1.22.0`. ([#2129](https://github.com/diffplug/spotless/pull/2129)) * Bump default `jackson` version to latest `2.14.2` -> `2.17.1`. ([#1685](https://github.com/diffplug/spotless/pull/1685)) @@ -21,7 +22,6 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `shfmt` version to latest `3.7.0` -> `3.8.0`. ([#2050](https://github.com/diffplug/spotless/pull/2050)) * Bump default `sortpom` version to latest `3.2.1` -> `4.0.0`. ([#2049](https://github.com/diffplug/spotless/pull/2049), [#2078](https://github.com/diffplug/spotless/pull/2078), [#2115](https://github.com/diffplug/spotless/pull/2115)) * Bump default `zjsonpatch` version to latest `0.4.14` -> `0.4.16`. ([#1969](https://github.com/diffplug/spotless/pull/1969)) -* Bump default `cleanthat` version to latest `2.16` -> `2.20`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) ### Removed * **BREAKING** Fully removed `Rome`, use `Biome` instead. ([#2119](https://github.com/diffplug/spotless/pull/2119)) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java index ae61dec331..4257e5595c 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 DiffPlug + * Copyright 2021-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,8 @@ import com.diffplug.spotless.Formatter; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.NeverUpToDateStep; +import com.diffplug.spotless.SerializedFunction; import com.diffplug.spotless.maven.MavenIntegrationHarness; class PluginFingerprintTest extends MavenIntegrationHarness { @@ -162,7 +164,7 @@ private static Model readPom(String xml) throws Exception { } private static FormatterStep formatterStep(String name) { - return FormatterStep.createNeverUpToDate(name, input -> input); + return NeverUpToDateStep.create(name, SerializedFunction.identity()); } private static Formatter formatter(FormatterStep... steps) { diff --git a/testlib/src/main/java/com/diffplug/spotless/NeverUpToDateStep.java b/testlib/src/main/java/com/diffplug/spotless/NeverUpToDateStep.java new file mode 100644 index 0000000000..53da84f4d8 --- /dev/null +++ b/testlib/src/main/java/com/diffplug/spotless/NeverUpToDateStep.java @@ -0,0 +1,64 @@ +/* + * Copyright 2024 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; + +import java.io.File; + +/** + * Formatter which is equal to itself, but not to any other Formatter. + */ +public class NeverUpToDateStep implements FormatterStep { + /** + * @param name + * The name of the formatter step + * @param function + * The function used by the formatter step + * @return A FormatterStep which will never report that it is up-to-date, because + * it is not equal to the serialized representation of itself. + */ + public static FormatterStep create( + String name, + SerializedFunction function) { + return new NeverUpToDateStep(name, function); + } + + private static final long serialVersionUID = 1L; + + private final String name; + private final SerializedFunction formatter; // initialized lazily + + NeverUpToDateStep(String name, SerializedFunction formatter) { + this.name = name; + this.formatter = formatter; + } + + @Override + public String getName() { + return name; + } + + @Override + public String format(String rawUnix, File file) throws Exception { + return formatter.apply(rawUnix); + } + + @Override + public void close() throws Exception { + if (formatter instanceof FormatterFunc.Closeable) { + ((FormatterFunc.Closeable) formatter).close(); + } + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/PaddedCellTest.java b/testlib/src/test/java/com/diffplug/spotless/PaddedCellTest.java index dae41678a4..28fc6a0710 100644 --- a/testlib/src/test/java/com/diffplug/spotless/PaddedCellTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/PaddedCellTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,17 +37,17 @@ class PaddedCellTest { @TempDir File rootFolder; - private void misbehaved(FormatterFunc step, String input, PaddedCell.Type expectedOutputType, String steps, String canonical) throws IOException { + private void misbehaved(SerializedFunction step, String input, PaddedCell.Type expectedOutputType, String steps, String canonical) throws IOException { testCase(step, input, expectedOutputType, steps, canonical, true); } - private void wellBehaved(FormatterFunc step, String input, PaddedCell.Type expectedOutputType, String canonical) throws IOException { + private void wellBehaved(SerializedFunction step, String input, PaddedCell.Type expectedOutputType, String canonical) throws IOException { testCase(step, input, expectedOutputType, canonical, canonical, false); } - private void testCase(FormatterFunc step, String input, PaddedCell.Type expectedOutputType, String expectedSteps, String canonical, boolean misbehaved) throws IOException { + private void testCase(SerializedFunction step, String input, PaddedCell.Type expectedOutputType, String expectedSteps, String canonical, boolean misbehaved) throws IOException { List formatterSteps = new ArrayList<>(); - formatterSteps.add(FormatterStep.createNeverUpToDate("step", step)); + formatterSteps.add(NeverUpToDateStep.create("step", step)); try (Formatter formatter = Formatter.builder() .lineEndingsPolicy(LineEnding.UNIX.createPolicy()) .encoding(StandardCharsets.UTF_8)