From 809fb4b0785803d96b2acde585db747f86e89c04 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 28 Sep 2023 15:28:26 -0700 Subject: [PATCH] Make GIT_ATTRIBUTES_FAST_ALLSAME faster. --- .../extra/GitAttributesLineEndings.java | 35 ++++++++++++ .../com/diffplug/spotless/LineEnding.java | 56 ++++--------------- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java index fb54be4ba0..c53e9a3e92 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java @@ -68,6 +68,41 @@ public final class GitAttributesLineEndings { // prevent direct instantiation private GitAttributesLineEndings() {} + /** + * Creates a line-endings policy which matches {@link #create(File, Supplier)}, + * which is much faster at the cost that every file under the policy + * is assumed to have the same line endings as the first file. + */ + public static LineEnding.Policy createFastAllSame(File projectDir, Supplier> toFormat) { + return new LazyAllTheSame(projectDir, toFormat); + } + + static class LazyAllTheSame extends LazyForwardingEquality implements LineEnding.Policy { + transient File projectDir; + transient Supplier> toFormat; + + public LazyAllTheSame(File projectDir, Supplier> toFormat) { + this.projectDir = projectDir; + this.toFormat = toFormat; + } + + @Override + protected String calculateState() throws Exception { + var files = toFormat.get().iterator(); + if (files.hasNext()) { + Runtime runtime = new RuntimeInit(projectDir).atRuntime(); + return runtime.getEndingFor(files.next()); + } else { + return LineEnding.UNIX.str(); + } + } + + @Override + public String getEndingFor(File file) { + return state(); + } + } + /** * Creates a line-endings policy whose serialized state is relativized against projectDir, * at the cost of eagerly evaluating the line-ending state of every target file when the diff --git a/lib/src/main/java/com/diffplug/spotless/LineEnding.java b/lib/src/main/java/com/diffplug/spotless/LineEnding.java index fa487a03b7..708699904c 100644 --- a/lib/src/main/java/com/diffplug/spotless/LineEnding.java +++ b/lib/src/main/java/com/diffplug/spotless/LineEnding.java @@ -59,52 +59,20 @@ public Policy createPolicy() { public Policy createPolicy(File projectDir, Supplier> toFormat) { Objects.requireNonNull(projectDir, "projectDir"); Objects.requireNonNull(toFormat, "toFormat"); - if (this != GIT_ATTRIBUTES && this != GIT_ATTRIBUTES_FAST_ALLSAME) { - return createPolicy(); + String gitAttributesMethod; + if (this == GIT_ATTRIBUTES) { + gitAttributesMethod = "create"; + } else if (this == GIT_ATTRIBUTES_FAST_ALLSAME) { + gitAttributesMethod = "createFastAllSame"; } else { - if (gitAttributesPolicyCreator == null) { - try { - Class clazz = Class.forName("com.diffplug.spotless.extra.GitAttributesLineEndings"); - Method method = clazz.getMethod("create", File.class, Supplier.class); - gitAttributesPolicyCreator = (proj, target) -> ThrowingEx.get(() -> (Policy) method.invoke(null, proj, target)); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - throw new IllegalStateException("LineEnding.GIT_ATTRIBUTES requires the spotless-lib-extra library, but it is not on the classpath", e); - } - } - // gitAttributesPolicyCreator will always be nonnull at this point - Policy policy = gitAttributesPolicyCreator.apply(projectDir, toFormat); - if (this == GIT_ATTRIBUTES) { - return policy; - } else if (this == GIT_ATTRIBUTES_FAST_ALLSAME) { - return new LazyAllTheSame(policy, toFormat); - } else { - throw new IllegalArgumentException("Unknown " + this); - } - } - } - - static class LazyAllTheSame extends LazyForwardingEquality implements Policy { - private transient Policy policy; - private transient Supplier> toFormat; - - public LazyAllTheSame(Policy policy, Supplier> toFormat) { - this.policy = policy; - this.toFormat = toFormat; - } - - @Override - protected String calculateState() throws Exception { - var files = toFormat.get().iterator(); - if (files.hasNext()) { - return policy.getEndingFor(files.next()); - } else { - return LineEnding.UNIX.str(); - } + return createPolicy(); } - - @Override - public String getEndingFor(File file) { - return state(); + try { + Class clazz = Class.forName("com.diffplug.spotless.extra.GitAttributesLineEndings"); + Method method = clazz.getMethod(gitAttributesMethod, File.class, Supplier.class); + return ThrowingEx.get(() -> (Policy) method.invoke(null, projectDir, toFormat)); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { + throw new IllegalStateException("LineEnding.GIT_ATTRIBUTES requires the spotless-lib-extra library, but it is not on the classpath", e); } }