15
15
*/
16
16
package com .diffplug .gradle .spotless ;
17
17
18
+ import java .io .Serializable ;
18
19
import java .nio .charset .Charset ;
19
20
import java .util .ArrayList ;
20
21
import java .util .Arrays ;
21
22
import java .util .List ;
22
23
import java .util .Map ;
23
24
import java .util .Objects ;
25
+ import java .util .function .Supplier ;
24
26
import java .util .regex .Pattern ;
25
27
import java .util .stream .Stream ;
26
28
29
31
import org .gradle .api .file .FileCollection ;
30
32
import org .gradle .api .internal .file .UnionFileCollection ;
31
33
34
+ import com .diffplug .common .base .Errors ;
35
+ import com .diffplug .common .base .Suppliers ;
32
36
import com .diffplug .common .base .Throwing ;
33
37
import com .diffplug .common .collect .ImmutableMap ;
34
38
@@ -149,6 +153,47 @@ protected FileCollection parseTarget(Object target) {
149
153
/** The steps that need to be added. */
150
154
protected List <FormatterStep > steps = new ArrayList <>();
151
155
156
+ /** Adds a new step. */
157
+ protected void addStep (FormatterStep newStep ) {
158
+ for (FormatterStep step : steps ) {
159
+ if (step .getName ().equals (name )) {
160
+ throw new GradleException ("Multiple steps with name '" + name + "' for spotless '" + name + "'" );
161
+ }
162
+ }
163
+ steps .add (newStep );
164
+ }
165
+
166
+ /**
167
+ * Spotless tracks what files have changed from run to run, so that it can run faster
168
+ * by only checking files which have changed.
169
+ *
170
+ * If you have changed a custom function, then you must increment this number so
171
+ * that spotless knows it needs to rerun the format check. This is not necessary
172
+ * if you don't use any custom functions.
173
+ *
174
+ * If you use a custom function and don't call bumpThisNumberIfACustomRuleChanges, then spotless
175
+ * cannot tell if you have changed the rules, and will be forced to always recheck all files.
176
+ */
177
+ public void bumpThisNumberIfACustomRuleChanges (int number ) {
178
+ globalKey = number ;
179
+ }
180
+
181
+ private Serializable globalKey = new NeverUpToDateBetweenRuns ();
182
+
183
+ static class NeverUpToDateBetweenRuns implements Serializable {
184
+ private static final long serialVersionUID = 1L ;
185
+
186
+ @ Override
187
+ public boolean equals (Object other ) {
188
+ return other == this ;
189
+ }
190
+
191
+ @ Override
192
+ public int hashCode () {
193
+ return System .identityHashCode (this );
194
+ }
195
+ }
196
+
152
197
/**
153
198
* Adds the given custom step, which is constructed lazily for performance reasons.
154
199
*
@@ -158,12 +203,9 @@ protected FileCollection parseTarget(Object target) {
158
203
* {@link #customLazyGroovy(String, com.diffplug.common.base.Throwing.Supplier)}.
159
204
*/
160
205
public void customLazy (String name , Throwing .Supplier <Throwing .Function <String , String >> formatterSupplier ) {
161
- for (FormatterStep step : steps ) {
162
- if (step .getName ().equals (name )) {
163
- throw new GradleException ("Multiple steps with name '" + name + "' for spotless '" + name + "'" );
164
- }
165
- }
166
- steps .add (FormatterStep .createLazy (name , formatterSupplier ));
206
+ Supplier <Throwing .Function <String , String >> nonThrowing = Errors .rethrow ().wrap (formatterSupplier );
207
+ Supplier <Throwing .Function <String , String >> memoized = Suppliers .memoize (nonThrowing );
208
+ addStep (FormatterStep .createLazy (name , () -> globalKey , (unusedKey , unix ) -> Errors .rethrow ().get (() -> memoized .get ().apply (unix ))));
167
209
}
168
210
169
211
/** Same as {@link #customLazy(String, com.diffplug.common.base.Throwing.Supplier)}, but for Groovy closures. */
@@ -263,7 +305,7 @@ public void indentWithTabs() {
263
305
* Spotless will look for a line that starts with this to know what the "top" is.
264
306
*/
265
307
public void licenseHeader (String licenseHeader , String delimiter ) {
266
- steps . add (FormatterStep .create (LicenseHeaderStep .NAME ,
308
+ addStep (FormatterStep .create (LicenseHeaderStep .NAME ,
267
309
new LicenseHeaderStep (licenseHeader , delimiter ),
268
310
LicenseHeaderStep ::format ));
269
311
}
@@ -275,7 +317,7 @@ public void licenseHeader(String licenseHeader, String delimiter) {
275
317
* Spotless will look for a line that starts with this to know what the "top" is.
276
318
*/
277
319
public void licenseHeaderFile (Object licenseHeaderFile , String delimiter ) {
278
- steps . add (FormatterStep .createLazy (LicenseHeaderStep .NAME ,
320
+ addStep (FormatterStep .createLazy (LicenseHeaderStep .NAME ,
279
321
() -> new LicenseHeaderStep (getProject ().file (licenseHeaderFile ), getEncoding (), delimiter ),
280
322
LicenseHeaderStep ::format ));
281
323
}
0 commit comments