Skip to content

Commit e876740

Browse files
committed
Merge branch 'main' into serializable-fence
2 parents d12de4f + 353736d commit e876740

File tree

101 files changed

+1953
-309
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+1953
-309
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ gradle-app.setting
1919
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
2020
!gradle-wrapper.jar
2121

22-
#Gradle-Lock files in _ext just serving as an input for lib-extra
23-
_ext/*/gradle/dependency-locks/*.lockfile
24-
2522
### Eclipse ###
2623
.metadata
2724
.gradle

CHANGES.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Added
14+
* `FileSignature.Promised` and `JarState.Promised` to facilitate round-trip serialization for the Gradle configuration cache. ([#1945](https://github.com/diffplug/spotless/pull/1945))
15+
### Removed
16+
* **BREAKING** Remove `JarState.getMavenCoordinate(String prefix)`. ([#1945](https://github.com/diffplug/spotless/pull/1945))
17+
### Fixed
18+
* Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990))
19+
20+
## [2.45.0] - 2024-01-23
21+
### Added
22+
* Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001))
23+
* Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009))
24+
25+
## [2.44.0] - 2024-01-15
26+
### Added
27+
* New static method to `DiffMessageFormatter` which allows to retrieve diffs with their line numbers ([#1960](https://github.com/diffplug/spotless/issues/1960))
28+
* Gradle - Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1994](https://github.com/diffplug/spotless/pull/1994))
29+
### Fixed
30+
* Fix empty files with biome >= 1.5.0 when formatting files that are in the ignore list of the biome configuration file. ([#1989](https://github.com/diffplug/spotless/pull/1989) fixes [#1987](https://github.com/diffplug/spotless/issues/1987))
31+
* Fix a regression in BufStep where the same arguments were being provided to every `buf` invocation. ([#1976](https://github.com/diffplug/spotless/issues/1976))
32+
### Changes
33+
* Use palantir-java-format 2.39.0 on Java 21. ([#1948](https://github.com/diffplug/spotless/pull/1948))
34+
* Bump default `ktlint` version to latest `1.0.1` -> `1.1.1`. ([#1973](https://github.com/diffplug/spotless/pull/1973))
35+
* Bump default `googleJavaFormat` version to latest `1.18.1` -> `1.19.2`. ([#1971](https://github.com/diffplug/spotless/pull/1971))
36+
* Bump default `diktat` version to latest `1.2.5` -> `2.0.0`. ([#1972](https://github.com/diffplug/spotless/pull/1972))
1337

1438
## [2.43.1] - 2023-12-04
1539
### Fixed

CONTRIBUTING.md

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ For the folders below in monospace text, they are published on MavenCentral at t
3636
| `lib-extra` | Contains the optional parts of Spotless which require external dependencies. `LineEnding.GIT_ATTRIBUTES` won't work unless `lib-extra` is available. |
3737
| `plugin-gradle` | Integrates spotless and all of its formatters into Gradle. |
3838
| `plugin-maven` | Integrates spotless and all of its formatters into Maven. |
39-
| `_ext` | Folder for generating glue jars (specifically packaging Eclipse jars from p2 for consumption using maven).
4039

4140
## How to add a new FormatterStep
4241

@@ -95,10 +94,31 @@ Here's a checklist for creating a new step for Spotless:
9594

9695
- [ ] Class name ends in Step, `SomeNewStep`.
9796
- [ ] Class has a public static method named `create` that returns a `FormatterStep`.
98-
- [ ] Has a test class named `SomeNewStepTest`.
97+
- [ ] Has a test class named `SomeNewStepTest` that uses `StepHarness` or `StepHarnessWithFile` to test the step.
98+
- [ ] Start with `StepHarness.forStep(myStep).supportsRoundTrip(false)`, and then add round trip support as described in the next section.
9999
- [ ] Test class has test methods to verify behavior.
100100
- [ ] Test class has a test method `equality()` which tests equality using `StepEqualityTester` (see existing methods for examples).
101101

102+
### Serialization roundtrip
103+
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:
105+
106+
- `RoundtripState` which must be roundtrip serializable but has no equality constraints
107+
- `FileSignature.Promised` for settings files and `JarState.Promised` for the classpath
108+
- `EqualityState` which will never be reserialized and its serialized form is used for equality / hashCode checks
109+
- `FileSignature` for settings files and `JarState` for the classpath
110+
111+
```java
112+
FormatterStep create(String name,
113+
RoundtripState roundTrip,
114+
SerializedFunction<RoundtripState, EqualityState> equalityFunc,
115+
SerializedFunction<EqualityState, FormatterFunc> formatterFunc)
116+
FormatterStep createLazy(String name,
117+
Supplier<RoundtripState> roundTrip,
118+
SerializedFunction<RoundtripState, EqualityState> equalityFunc,
119+
SerializedFunction<EqualityState, FormatterFunc> formatterFunc)
120+
```
121+
102122
### Third-party dependencies via reflection or compile-only source sets
103123

104124
Most formatters are going to use some kind of third-party jar. Spotless integrates with many formatters, some of which have incompatible transitive dependencies. To address this, we resolve third-party dependencies using [`JarState`](https://github.com/diffplug/spotless/blob/b26f0972b185995d7c6a7aefa726c146d24d9a82/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java#L118). To call methods on the classes in that `JarState`, you can either use reflection or a compile-only source set. See [#524](https://github.com/diffplug/spotless/issues/524) for examples of both approaches.
@@ -119,24 +139,6 @@ There are many great formatters (prettier, clang-format, black, etc.) which live
119139

120140
Because of Spotless' up-to-date checking and [git ratcheting](https://github.com/diffplug/spotless/tree/main/plugin-gradle#ratchet), Spotless actually doesn't have to call formatters very often, so even an expensive shell call for every single invocation isn't that bad. Anything that works is better than nothing, and we can always speed things up later if it feels too slow (but it probably won't).
121141

122-
## How to enable the `_ext` projects
123-
124-
The `_ext` projects are disabled per default, since:
125-
126-
* some of the projects perform vast downloads at configuration time
127-
* the downloaded content may change on server side and break CI builds
128-
129-
130-
The `_ext` can be activated via the root project property `com.diffplug.spotless.include.ext`.
131-
132-
Activate the property via command line, like for example:
133-
134-
```
135-
gradlew -Pcom.diffplug.spotless.include.ext=true build
136-
```
137-
138-
Or set the property in your user `gradle.properties` file, which is especially recommended if you like to work with the `_ext` projects using IDEs.
139-
140142
## How to add a new plugin for a build system
141143

142144
The gist of it is that you will have to:
@@ -151,6 +153,37 @@ The gist of it is that you will have to:
151153

152154
If you get something running, we'd love to host your plugin within this repo as a peer to `plugin-gradle` and `plugin-maven`.
153155

156+
## Run tests
157+
158+
To run all tests, simply do
159+
160+
> gradlew test
161+
162+
Since that takes some time, you might only want to run the tests
163+
concerning what you are working on:
164+
165+
```shell
166+
# Run only from test from the "lib" project
167+
gradlew :testlib:test --tests com.diffplug.spotless.generic.IndentStepTest
168+
169+
# Run only one test from the "plugin-maven" project
170+
gradlew :plugin-maven:test --tests com.diffplug.spotless.maven.pom.SortPomMavenTest
171+
172+
# Run only one test from the "plugin-gradle" project
173+
gradlew :plugin-gradle:test --tests com.diffplug.gradle.spotless.FreshMarkExtensionTest
174+
```
175+
176+
## Check and format code
177+
178+
Before creating a pull request, you might want to format (yes, spotless is formatted by spotless)
179+
the code and check for possible bugs
180+
181+
* `./gradlew spotlessApply`
182+
* `./gradlew spotbugsMain`
183+
184+
These checks are also run by the automated pipeline when you submit a pull request, if
185+
the pipeline fails, first check if the code is formatted and no bugs were found.
186+
154187
## Integration testing
155188

156189
### Gradle - locally

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Maven Plugin](https://img.shields.io/maven-central/v/com.diffplug.spotless/spotless-maven-plugin?color=blue&label=maven%20plugin)](plugin-maven)
55
[![SBT Plugin](https://img.shields.io/badge/sbt%20plugin-0.1.3-blue)](https://github.com/moznion/sbt-spotless)
66

7-
Spotless can format &lt;antlr | c | c# | c++ | css | flow | graphql | groovy | html | java | javascript | json | jsx | kotlin | less | license headers | markdown | objective-c | protobuf | python | scala | scss | sql | typeScript | vue | yaml | anything> using &lt;gradle | maven | sbt | anything>.
7+
Spotless can format &lt;antlr | c | c# | c++ | css | flow | graphql | groovy | html | java | javascript | json | jsx | kotlin | less | license headers | markdown | objective-c | protobuf | python | scala | scss | shell | sql | typeScript | vue | yaml | anything> using &lt;gradle | maven | sbt | anything>.
88

99
You probably want one of the links below:
1010

@@ -75,8 +75,10 @@ lib('generic.ReplaceRegexStep') +'{{yes}} | {{yes}}
7575
lib('generic.ReplaceStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
7676
lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
7777
lib('antlr4.Antlr4FormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
78+
lib('biome.BiomeStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
7879
lib('cpp.ClangFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
7980
extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
81+
lib('go.GofmtFormatStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
8082
lib('gherkin.GherkinUtilsStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
8183
extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
8284
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
@@ -101,8 +103,8 @@ lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}}
101103
lib('pom.SortPomStepStep') +'{{no}} | {{yes}} | {{no}} | {{no}} |',
102104
lib('protobuf.BufStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
103105
lib('python.BlackStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
104-
lib('biome.BiomeStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
105106
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
107+
lib('shell.ShfmtStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
106108
lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
107109
extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
108110
lib('yaml.JacksonYamlStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
@@ -127,8 +129,10 @@ lib('yaml.JacksonYamlStep') +'{{yes}} | {{yes}}
127129
| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
128130
| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
129131
| [`antlr4.Antlr4FormatterStep`](lib/src/main/java/com/diffplug/spotless/antlr4/Antlr4FormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
132+
| [`biome.BiomeStep`](lib/src/main/java/com/diffplug/spotless/biome/BiomeStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
130133
| [`cpp.ClangFormatStep`](lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
131134
| [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
135+
| [`go.GofmtFormatStep`](lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
132136
| [`gherkin.GherkinUtilsStep`](lib/src/main/java/com/diffplug/spotless/gherkin/GherkinUtilsStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
133137
| [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
134138
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
@@ -153,8 +157,8 @@ lib('yaml.JacksonYamlStep') +'{{yes}} | {{yes}}
153157
| [`pom.SortPomStepStep`](lib/src/main/java/com/diffplug/spotless/pom/SortPomStepStep.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: |
154158
| [`protobuf.BufStep`](lib/src/main/java/com/diffplug/spotless/protobuf/BufStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
155159
| [`python.BlackStep`](lib/src/main/java/com/diffplug/spotless/python/BlackStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
156-
| [`biome.BiomeStep`](lib/src/main/java/com/diffplug/spotless/biome/BiomeStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
157160
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
161+
| [`shell.ShfmtStep`](lib/src/main/java/com/diffplug/spotless/shell/ShfmtStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
158162
| [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
159163
| [`wtp.EclipseWtpFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/wtp/EclipseWtpFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
160164
| [`yaml.JacksonYamlStep`](lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |

gradle/special-tests.gradle

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
apply plugin: 'com.adarshr.test-logger'
2+
3+
// See com.diffplug.spotless.tag package for available JUnit 5 @Tag annotations
24
def special = [
3-
'Npm',
4-
'Black',
5-
'Clang',
6-
'Buf'
5+
'black',
6+
'buf',
7+
'clang',
8+
'gofmt',
9+
'npm',
10+
'shfmt'
711
]
812

913
boolean isCiServer = System.getenv().containsKey("CI")
1014
tasks.withType(Test).configureEach {
11-
// See com.diffplug.spotless.tag package for available JUnit 5 @Tag annotations
12-
useJUnitPlatform {
13-
excludeTags special as String[]
14-
}
1515
if (isCiServer) {
1616
retry {
1717
maxRetries = 2
@@ -25,9 +25,13 @@ tasks.withType(Test).configureEach {
2525
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
2626
}
2727
}
28-
28+
tasks.named('test').configure {
29+
useJUnitPlatform {
30+
excludeTags special as String[]
31+
}
32+
}
2933
special.forEach { tag ->
30-
tasks.register("test${tag}", Test) {
34+
tasks.register("test${tag.capitalize()}", Test) {
3135
useJUnitPlatform { includeTags tag }
3236
}
3337
}

lib-extra/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ version = rootProject.spotlessChangelog.versionNext
77
apply from: rootProject.file('gradle/java-setup.gradle')
88
apply from: rootProject.file('gradle/java-publish.gradle')
99

10-
String VER_SOLSTICE = '1.7.4'
10+
String VER_SOLSTICE = '1.7.5'
1111
dependencies {
1212
api projects.lib
1313
// misc useful utilities

lib-extra/src/main/java/com/diffplug/spotless/extra/EclipseBasedStepBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2023 DiffPlug
2+
* Copyright 2016-2024 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.

lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2023 DiffPlug
2+
* Copyright 2016-2024 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.
@@ -113,7 +113,7 @@ public FormatterStep build() {
113113
}
114114
var classpath = new ArrayList<File>();
115115
var mavenDeps = new ArrayList<String>();
116-
mavenDeps.add("dev.equo.ide:solstice:1.7.4");
116+
mavenDeps.add("dev.equo.ide:solstice:1.7.5");
117117
mavenDeps.add("com.diffplug.durian:durian-swt.os:4.2.0");
118118
mavenDeps.addAll(query.getJarsOnMavenCentral());
119119
classpath.addAll(mavenProvisioner.provisionWithTransitives(false, mavenDeps));

lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import java.nio.file.Path;
2525
import java.util.List;
2626
import java.util.ListIterator;
27+
import java.util.Map;
2728
import java.util.Objects;
2829

2930
import org.eclipse.jgit.diff.DiffFormatter;
31+
import org.eclipse.jgit.diff.Edit;
3032
import org.eclipse.jgit.diff.EditList;
3133
import org.eclipse.jgit.diff.MyersDiff;
3234
import org.eclipse.jgit.diff.RawText;
@@ -234,6 +236,19 @@ private void addIntendedLine(String indent, String line) {
234236
* sequence (\n, \r, \r\n).
235237
*/
236238
private String diff(File file) throws IOException {
239+
return diff(formatter, file).getValue();
240+
}
241+
242+
/**
243+
* Returns a map entry with value being a git-style diff between the contents of the given file and what those contents would
244+
* look like if formatted using the given formatter. Does not end with any newline
245+
* sequence (\n, \r, \r\n). The key of the map entry is the 0-based line where the first difference occurred.
246+
*/
247+
public static Map.Entry<Integer, String> diff(Formatter formatter, File file) throws IOException {
248+
return diff(new CleanProviderFormatter(formatter), file);
249+
}
250+
251+
private static Map.Entry<Integer, String> diff(CleanProvider formatter, File file) throws IOException {
237252
String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding());
238253
String rawUnix = LineEnding.toUnix(raw);
239254
String formatted = formatter.getFormatted(file, rawUnix);
@@ -248,13 +263,13 @@ private String diff(File file) throws IOException {
248263
}
249264

250265
/**
251-
* Returns a git-style diff between the two unix strings.
266+
* Returns a map entry with value being a git-style diff between the two unix strings and key being the 0-based line of the first difference (in the dirty string)
252267
* <p>
253268
* Output has no trailing newlines.
254269
* <p>
255270
* Boolean args determine whether whitespace or line endings will be visible.
256271
*/
257-
private static String diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException {
272+
private static Map.Entry<Integer, String> diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException {
258273
dirty = visibleWhitespaceLineEndings(dirty, whitespace, lineEndings);
259274
clean = visibleWhitespaceLineEndings(clean, whitespace, lineEndings);
260275

@@ -271,7 +286,11 @@ private static String diffWhitespaceLineEndings(String dirty, String clean, bool
271286

272287
// we don't need the diff to show this, since we display newlines ourselves
273288
formatted = formatted.replace("\\ No newline at end of file\n", "");
274-
return NEWLINE_MATCHER.trimTrailingFrom(formatted);
289+
return Map.entry(getLineOfFirstDifference(edits), NEWLINE_MATCHER.trimTrailingFrom(formatted));
290+
}
291+
292+
private static int getLineOfFirstDifference(EditList edits) {
293+
return edits.stream().mapToInt(Edit::getBeginA).min().getAsInt();
275294
}
276295

277296
private static final CharMatcher NEWLINE_MATCHER = CharMatcher.is('\n');

0 commit comments

Comments
 (0)