Skip to content

Commit c1357f5

Browse files
committed
The new FormatterStep.create() and createLazy() utilized anonymous classes which captured their parameters in non-transient fields. Thanks to FindBugs for spotting the error! New implementation ensures that the *only state* is the serializable key.
1 parent 452fbd9 commit c1357f5

File tree

2 files changed

+89
-37
lines changed

2 files changed

+89
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2016 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.gradle.spotless;
17+
18+
import java.io.File;
19+
import java.io.Serializable;
20+
import java.util.Objects;
21+
import java.util.function.BiFunction;
22+
23+
import com.diffplug.common.base.Throwing;
24+
import com.diffplug.gradle.spotless.FormatterStep.Strict;
25+
26+
/**
27+
* Standard implementation of FormatExtension which cleanly enforces
28+
* separation of serializable configuration and a pure format function.
29+
*/
30+
abstract class FormatExtensionStandardImpl<Key extends Serializable> extends Strict<Key> {
31+
private static final long serialVersionUID = 1L;
32+
33+
/** Transient because only the state matters. */
34+
final transient String name;
35+
/** Transient because only the state matters. */
36+
final transient BiFunction<Key, String, String> formatter;
37+
38+
public FormatExtensionStandardImpl(String name, BiFunction<Key, String, String> formatter) {
39+
this.name = Objects.requireNonNull(name);
40+
this.formatter = Objects.requireNonNull(formatter);
41+
}
42+
43+
@Override
44+
public String getName() {
45+
return name;
46+
}
47+
48+
@Override
49+
protected String format(Key key, String rawUnix, File file) {
50+
return formatter.apply(key, rawUnix);
51+
}
52+
53+
static class Eager<Key extends Serializable> extends FormatExtensionStandardImpl<Key> {
54+
private static final long serialVersionUID = 1L;
55+
56+
/** Transient because the key is persisted by the superclass. */
57+
final transient Key key;
58+
59+
public Eager(String name, Key key, BiFunction<Key, String, String> formatter) {
60+
super(name, formatter);
61+
this.key = Objects.requireNonNull(key);
62+
}
63+
64+
@Override
65+
protected Key calculateKey() throws Exception {
66+
return key;
67+
}
68+
}
69+
70+
static class Lazy<Key extends Serializable> extends FormatExtensionStandardImpl<Key> {
71+
private static final long serialVersionUID = 1L;
72+
73+
/** Transient because the key is persisted by the superclass. */
74+
final transient Throwing.Specific.Supplier<Key, Exception> keySupplier;
75+
76+
public Lazy(String name, Throwing.Specific.Supplier<Key, Exception> keySupplier, BiFunction<Key, String, String> formatter) {
77+
super(name, formatter);
78+
this.keySupplier = Objects.requireNonNull(keySupplier);
79+
}
80+
81+
@Override
82+
protected Key calculateKey() throws Exception {
83+
return keySupplier.get();
84+
}
85+
}
86+
}

src/main/java/com/diffplug/gradle/spotless/FormatterStep.java

+3-37
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public interface FormatterStep extends Serializable {
3939
/**
4040
* Returns a formatted version of the given content.
4141
*
42-
* @param raw
42+
* @param rawUnix
4343
* File's content, guaranteed to have unix-style newlines ('\n')
4444
* @param file
4545
* the File which is being formatted
@@ -92,24 +92,7 @@ public static <Key extends Serializable> FormatterStep createLazy(
9292
String name,
9393
Throwing.Specific.Supplier<Key, Exception> keySupplier,
9494
BiFunction<Key, String, String> formatter) {
95-
return new Strict<Key>() {
96-
private static final long serialVersionUID = 1L;
97-
98-
@Override
99-
public String getName() {
100-
return name;
101-
}
102-
103-
@Override
104-
protected Key calculateKey() throws Exception {
105-
return keySupplier.get();
106-
}
107-
108-
@Override
109-
protected String format(Key key, String rawUnix, File file) {
110-
return formatter.apply(key, rawUnix);
111-
}
112-
};
95+
return new FormatExtensionStandardImpl.Lazy<>(name, keySupplier, formatter);
11396
}
11497

11598
/**
@@ -126,24 +109,7 @@ public static <Key extends Serializable> FormatterStep create(
126109
String name,
127110
Key key,
128111
BiFunction<Key, String, String> formatter) {
129-
return new Strict<Key>() {
130-
private static final long serialVersionUID = 1L;
131-
132-
@Override
133-
public String getName() {
134-
return name;
135-
}
136-
137-
@Override
138-
protected Key calculateKey() throws Exception {
139-
return key;
140-
}
141-
142-
@Override
143-
protected String format(Key key, String rawUnix, File file) {
144-
return formatter.apply(key, rawUnix);
145-
}
146-
};
112+
return new FormatExtensionStandardImpl.Eager<>(name, key, formatter);
147113
}
148114

149115
/** A FormatterStep which doesn't depend on the input file. */

0 commit comments

Comments
 (0)