Skip to content

Commit 4f5bf51

Browse files
committed
Update contributor docs a bit.
1 parent baea8c9 commit 4f5bf51

File tree

1 file changed

+14
-16
lines changed

1 file changed

+14
-16
lines changed

CONTRIBUTING.md

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@ In order to use and combine `FormatterStep`, you first create a `Formatter`, whi
1010

1111
- an encoding
1212
- a list of `FormatterStep`
13-
- a line endings policy (`LineEnding.GIT_ATTRIBUTES` is almost always the best choice)
13+
- a line endings policy (`LineEnding.GIT_ATTRIBUTES_FAST_ALLSAME` is almost always the best choice)
1414

15-
Once you have an instance of `Formatter`, you can call `boolean isClean(File)`, or `void applyTo(File)` to either check or apply formatting to a file. Spotless will then:
15+
Once you have an instance of `Formatter`, you can call `DirtyState.of(Formatter, File)`. Under the hood, Spotless will:
1616

1717
- parse the raw bytes into a String according to the encoding
1818
- normalize its line endings to `\n`
1919
- pass the unix string to each `FormatterStep` one after the other
20+
- check for idempotence problems, and repeatedly apply the steps until the [result is stable](PADDEDCELL.md).
2021
- apply line endings according to the policy
2122

2223
You can also use lower-level methods like `String compute(String unix, File file)` if you'd like to do lower-level processing.
2324

2425
All `FormatterStep` implement `Serializable`, `equals`, and `hashCode`, so build systems that support up-to-date checks can easily and correctly determine if any actions need to be taken.
2526

26-
Spotless also provides `PaddedCell`, which makes it easy to diagnose and correct idempotence problems.
27-
2827
## Project layout
2928

3029
For the folders below in monospace text, they are published on MavenCentral at the coordinate `com.diffplug.spotless:spotless-${FOLDER_NAME}`. The other folders are dev infrastructure.
@@ -39,15 +38,16 @@ For the folders below in monospace text, they are published on MavenCentral at t
3938

4039
## How to add a new FormatterStep
4140

42-
The easiest way to create a FormatterStep is `FormatterStep createNeverUpToDate(String name, FormatterFunc function)`, which you can use like this:
41+
The easiest way to create a FormatterStep is to just create `class FooStep implements FormatterStep`. It has one abstract method which is the formatting function, and you're ready to tinker. To work with the build plugins, this class will need to
4342

44-
```java
45-
FormatterStep identityStep = FormatterStep.createNeverUpToDate("identity", unixStr -> unixStr)
46-
```
43+
- implement equality and hashcode
44+
- support lossless roundtrip serialization
45+
46+
You can use `StepHarness` (if you don't care about the `File` argument) or `StepHarnessWithFile` to test. The harness will roundtrip serialize your step, check that it's equal to itself, and then perform all tests on the roundtripped step.
4747

48-
This creates a step which will fail up-to-date checks (it is equal only to itself), and will use the function you passed in to do the formatting pass.
48+
## Implementing equality in terms of serialization
4949

50-
To create a step which can handle up-to-date checks properly, use the method `<State extends Serializable> FormatterStep create(String name, State state, Function<State, FormatterFunc> stateToFormatter)`. Here's an example:
50+
Spotless has infrastructure which uses the serialized form of your step to implement equality for you. Here is an example:
5151

5252
```java
5353
public final class ReplaceStep {
@@ -62,10 +62,10 @@ public final class ReplaceStep {
6262
private static final class State implements Serializable {
6363
private static final long serialVersionUID = 1L;
6464

65-
private final CharSequence target;
66-
private final CharSequence replacement;
65+
private final String target;
66+
private final String replacement;
6767

68-
State(CharSequence target, CharSequence replacement) {
68+
State(String target, String replacement) {
6969
this.target = target;
7070
this.replacement = replacement;
7171
}
@@ -82,8 +82,6 @@ The `FormatterStep` created above implements `equals` and `hashCode` based on th
8282
Oftentimes, a rule's state will be expensive to compute. `EclipseFormatterStep`, for example, depends on a formatting file. Ideally, we would like to only pay the cost of the I/O needed to load that file if we have to - we'd like to create the FormatterStep now but load its state lazily at the last possible moment. For this purpose, each of the `FormatterStep.create` methods has a lazy counterpart. Here are their signatures:
8383

8484
```java
85-
FormatterStep createNeverUpToDate (String name, FormatterFunc function )
86-
FormatterStep createNeverUpToDateLazy(String name, Supplier<FormatterFunc> functionSupplier)
8785
FormatterStep create (String name, State state , Function<State, FormatterFunc> stateToFormatter)
8886
FormatterStep createLazy(String name, Supplier<State> stateSupplier, Function<State, FormatterFunc> stateToFormatter)
8987
```
@@ -101,7 +99,7 @@ Here's a checklist for creating a new step for Spotless:
10199

102100
### Serialization roundtrip
103101

104-
In order to support Gradle's configuration cache, all `FormatterStep` must be round-trip serializable. This is a bit tricky because step equality is based on the serialized form of the state, and `transient` is used to take absolute paths out of the equality check. To make this work, roundtrip compatible steps actually have *two* states:
102+
In order to support Gradle's configuration cache, all `FormatterStep` must be round-trip serializable. This is a bit tricky because step equality is based on the serialized form of the state, and `transient` can be used to take absolute paths out of the equality check. To make this work, roundtrip compatible steps can actually have *two* states:
105103

106104
- `RoundtripState` which must be roundtrip serializable but has no equality constraints
107105
- `FileSignature.Promised` for settings files and `JarState.Promised` for the classpath

0 commit comments

Comments
 (0)