Skip to content

Commit e4d6c49

Browse files
committed
Introduce FileSignature.RoundTrippable and JarState.Promised so that maven-based formatters can be safely roundtripped.
1 parent 317b2ac commit e4d6c49

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

lib/src/main/java/com/diffplug/spotless/FileSignature.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2021 DiffPlug
2+
* Copyright 2016-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import java.util.Locale;
3434
import java.util.Map;
3535

36+
import edu.umd.cs.findbugs.annotations.Nullable;
3637
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
3738

3839
/** Computes a signature for any needed files. */
@@ -43,6 +44,8 @@ public final class FileSignature implements Serializable {
4344
* Transient because not needed to uniquely identify a FileSignature instance, and also because
4445
* Gradle only needs this class to be Serializable so it can compare FileSignature instances for
4546
* incremental builds.
47+
*
48+
* We don't want these absolute paths to screw up buildcache keys.
4649
*/
4750
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
4851
private final transient List<File> files;
@@ -93,6 +96,45 @@ private FileSignature(final List<File> files) throws IOException {
9396
}
9497
}
9598

99+
/** A view of `FileSignature` which can be safely roundtripped. */
100+
public static class RoundTrippable implements Serializable {
101+
private final List<File> files;
102+
private transient @Nullable FileSignature cached;
103+
104+
private RoundTrippable(List<File> files, FileSignature cached) {
105+
this.files = files;
106+
this.cached = cached;
107+
}
108+
109+
public FileSignature stripAbsolutePaths() throws IOException {
110+
if (cached == null) {
111+
// null when restored via serialization
112+
cached = new FileSignature(files);
113+
}
114+
return cached;
115+
}
116+
}
117+
118+
public RoundTrippable roundTrippable() {
119+
return new RoundTrippable(files, this);
120+
}
121+
122+
public static @Nullable RoundTrippable roundTrippableNullable(@Nullable FileSignature signature) {
123+
if (signature != null) {
124+
return signature.roundTrippable();
125+
} else {
126+
return null;
127+
}
128+
}
129+
130+
public static @Nullable FileSignature stripAbsolutePathsNullable(@Nullable RoundTrippable roundTrippable) throws IOException {
131+
if (roundTrippable != null) {
132+
return roundTrippable.stripAbsolutePaths();
133+
} else {
134+
return null;
135+
}
136+
}
137+
96138
/** Returns all of the files in this signature, throwing an exception if there are more or less than 1 file. */
97139
public Collection<File> files() {
98140
return Collections.unmodifiableList(files);

lib/src/main/java/com/diffplug/spotless/JarState.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.File;
1919
import java.io.IOException;
20+
import java.io.ObjectStreamException;
2021
import java.io.Serializable;
2122
import java.net.URI;
2223
import java.net.URL;
@@ -36,6 +37,48 @@
3637
* catch changes in a SNAPSHOT version.
3738
*/
3839
public final class JarState implements Serializable {
40+
/** A lazily evaluated JarState, which becomes a set of files when serialized. */
41+
public static class Promised implements Serializable {
42+
private final transient ThrowingEx.Supplier<JarState> supplier;
43+
private FileSignature.RoundTrippable cached;
44+
45+
public Promised(ThrowingEx.Supplier<JarState> supplier) {
46+
this.supplier = supplier;
47+
}
48+
49+
public JarState get() {
50+
try {
51+
if (cached == null) {
52+
JarState result = supplier.get();
53+
cached = result.fileSignature.roundTrippable();
54+
return result;
55+
}
56+
return new JarState(cached.stripAbsolutePaths());
57+
} catch (Exception e) {
58+
throw ThrowingEx.asRuntime(e);
59+
}
60+
}
61+
62+
// override serialize output
63+
private void writeObject(java.io.ObjectOutputStream out)
64+
throws IOException {
65+
get();
66+
out.defaultWriteObject();
67+
}
68+
69+
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
70+
in.defaultReadObject();
71+
}
72+
73+
private void readObjectNoData() throws ObjectStreamException {
74+
throw new UnsupportedOperationException();
75+
}
76+
}
77+
78+
public static Promised promise(ThrowingEx.Supplier<JarState> supplier) {
79+
return new Promised(supplier);
80+
}
81+
3982
private static final long serialVersionUID = 1L;
4083

4184
private final FileSignature fileSignature;

0 commit comments

Comments
 (0)