Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
- Add `javaparserVersion` option to the Cleanthat step, allowing callers to override the JavaParser version pulled in transitively by Cleanthat. ([#2903](https://github.com/diffplug/spotless/pull/2903))
### Changes
- Bump default `cleanthat` version `2.24` -> `2.25`. ([#2903](https://github.com/diffplug/spotless/pull/2903))

## [4.5.0] - 2026-03-18
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private String doApply(String input, File file) throws IOException {

JavaRefactorer refactorer = new JavaRefactorer(engineProperties, refactorerProperties);

LOGGER.debug("Processing sourceJdk={} included={} excluded={}", jdkVersion, included, excluded, includeDraft);
LOGGER.debug("Processing sourceJdk={} included={} excluded={} includeDraft={}", jdkVersion, included, excluded, includeDraft);
LOGGER.debug("Available mutators: {}", JavaRefactorer.getAllIncluded());

PathAndContent pathAndContent = new PathAndContent(file.toPath(), input);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2025 DiffPlug
* Copyright 2023-2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,6 +21,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Expand All @@ -31,6 +32,8 @@
import com.diffplug.spotless.Jvm;
import com.diffplug.spotless.Provisioner;

import edu.umd.cs.findbugs.annotations.Nullable;

/**
* Enables CleanThat as a SpotLess step.
*
Expand All @@ -42,26 +45,30 @@ public final class CleanthatJavaStep implements Serializable {
private static final long serialVersionUID = 1L;
private static final String NAME = "cleanthat";
private static final String MAVEN_COORDINATE = "io.github.solven-eu.cleanthat:java";
private static final String JAVAPARSER_MAVEN_COORDINATE = "com.github.javaparser:javaparser-symbol-solver-core";
/**
* CleanThat changelog is available at <a href="https://github.com/solven-eu/cleanthat/blob/master/CHANGES.MD">here</a>.
*/
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(17, "2.24");
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(17, "2.25");

private final JarState.Promised jarState;
private final String version;
private final String javaparserVersion;
private final String sourceJdkVersion;
private final List<String> included;
private final List<String> excluded;
private final boolean includeDraft;

private CleanthatJavaStep(JarState.Promised jarState,
String version,
String javaparserVersion,
String sourceJdkVersion,
List<String> included,
List<String> excluded,
boolean includeDraft) {
this.jarState = jarState;
this.version = version;
this.javaparserVersion = javaparserVersion;

this.sourceJdkVersion = sourceJdkVersion;
this.included = included;
Expand All @@ -76,7 +83,14 @@ public static FormatterStep create(Provisioner provisioner) {

/** Creates a step that applies default CleanThat mutators. */
public static FormatterStep create(String version, Provisioner provisioner) {
return createWithStepName(NAME, MAVEN_COORDINATE, version, defaultSourceJdk(), defaultMutators(), defaultExcludedMutators(), defaultIncludeDraft(), provisioner);
return createWithStepName(NAME, MAVEN_COORDINATE, version, defaultJavaparserVersion(), defaultSourceJdk(), defaultMutators(), defaultExcludedMutators(), defaultIncludeDraft(), provisioner);
}

/**
* Default JavaParser version: {@code null}, meaning whichever transitive version is brought in by Cleanthat.
*/
@Nullable public static String defaultJavaparserVersion() {
return null;
}

public static String defaultSourceJdk() {
Expand Down Expand Up @@ -106,6 +120,7 @@ public static boolean defaultIncludeDraft() {
static FormatterStep createWithStepName(String stepName,
String groupArtifact,
String version,
String javaparserVersion,
String sourceJdkVersion,
List<String> included,
List<String> excluded,
Expand All @@ -117,8 +132,14 @@ static FormatterStep createWithStepName(String stepName,
}
Objects.requireNonNull(version, "version");
Objects.requireNonNull(provisioner, "provisioner");
List<String> coordinates = new ArrayList<>();
coordinates.add(groupArtifact + ":" + version);
if (javaparserVersion != null) {
// Added alongside Cleanthat so dependency resolution can upgrade the transitive JavaParser.
coordinates.add(JAVAPARSER_MAVEN_COORDINATE + ":" + javaparserVersion);
}
return FormatterStep.create(stepName,
new CleanthatJavaStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, sourceJdkVersion, included, excluded, includeDraft),
new CleanthatJavaStep(JarState.promise(() -> JarState.from(coordinates, provisioner)), version, javaparserVersion, sourceJdkVersion, included, excluded, includeDraft),
CleanthatJavaStep::equalityState,
State::createFormat);
}
Expand All @@ -131,7 +152,19 @@ public static FormatterStep create(String groupArtifact,
List<String> excluded,
boolean includeDraft,
Provisioner provisioner) {
return createWithStepName(NAME, groupArtifact, version, sourceJdkVersion, included, excluded, includeDraft, provisioner);
return createWithStepName(NAME, groupArtifact, version, defaultJavaparserVersion(), sourceJdkVersion, included, excluded, includeDraft, provisioner);
}

/** Creates a step that applies selected CleanThat mutators, with a custom JavaParser version. */
public static FormatterStep create(String groupArtifact,
String version,
String javaparserVersion,
String sourceJdkVersion,
List<String> included,
List<String> excluded,
boolean includeDraft,
Provisioner provisioner) {
return createWithStepName(NAME, groupArtifact, version, javaparserVersion, sourceJdkVersion, included, excluded, includeDraft, provisioner);
}

/** Get default formatter version */
Expand All @@ -144,7 +177,7 @@ public static String defaultGroupArtifact() {
}

private State equalityState() {
return new State(jarState.get(), version, sourceJdkVersion, included, excluded, includeDraft);
return new State(jarState.get(), version, javaparserVersion, sourceJdkVersion, included, excluded, includeDraft);
}

private static final class State implements Serializable {
Expand All @@ -153,13 +186,15 @@ private static final class State implements Serializable {

private final JarState jarState;
private final String version;
private final String javaparserVersion;
private final String sourceJdkVersion;
private final List<String> included;
private final List<String> excluded;
private final boolean includeDraft;

State(JarState jarState,
String version,
String javaparserVersion,
String sourceJdkVersion,
List<String> included,
List<String> excluded,
Expand All @@ -168,6 +203,7 @@ private static final class State implements Serializable {
ModuleHelper.doOpenInternalPackagesIfRequired();
this.jarState = jarState;
this.version = version;
this.javaparserVersion = javaparserVersion;
this.sourceJdkVersion = sourceJdkVersion;
this.included = included;
this.excluded = excluded;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2025 DiffPlug
* Copyright 2016-2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,7 +53,7 @@ public static FormatterStep create(String unusedImportRemover, Provisioner provi
case GJF:
return GoogleJavaFormatStep.createRemoveUnusedImportsOnly(provisioner);
case CLEANTHAT:
return CleanthatJavaStep.createWithStepName(NAME, CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), "99.9", List.of(CLEANTHAT_MUTATOR), List.of(), false, provisioner);
return CleanthatJavaStep.createWithStepName(NAME, CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), CleanthatJavaStep.defaultJavaparserVersion(), "99.9", List.of(CLEANTHAT_MUTATOR), List.of(), false, provisioner);
default:
throw new IllegalArgumentException("Invalid unusedImportRemover: " + unusedImportRemover);
}
Expand Down
3 changes: 3 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]
### Added
- Add `withIndentStyle` and `withIndentSize` configuration to `tableTestFormatter` for setting the fallback indent when no `.editorconfig` is found. ([#2893](https://github.com/diffplug/spotless/pull/2893))
- Add `javaparserVersion(...)` to `cleanthat`, allowing users to override the JavaParser version pulled in transitively by Cleanthat. ([#2903](https://github.com/diffplug/spotless/pull/2903))
### Fixed
- Fix `tableTestFormatter` editorconfig cache not honoring `.editorconfig` changes across Gradle daemon runs due to a shared static `EditorConfigProvider`. ([#2893](https://github.com/diffplug/spotless/pull/2893))
### Changes
- Bump default `cleanthat` version `2.24` -> `2.25`. ([#2903](https://github.com/diffplug/spotless/pull/2903))

## [8.4.0] - 2026-03-18
### Added
Expand Down
3 changes: 2 additions & 1 deletion plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ spotless {
// optional: you can specify a specific version and/or config file
cleanthat()
.groupArtifact('io.github.solven-eu.cleanthat:java') // Optional. Default is 'io.github.solven-eu.cleanthat:java'
.version('2.8') // You may force a custom version of Cleanthat
.version('2.25') // You may force a custom version of Cleanthat
.javaparserVersion('3.26.4') // Advanced: override the JavaParser version transitively pulled by Cleanthat
.sourceCompatibility('1.7') // default is '1.7'
.addMutator('SafeAndConsensual') // Default includes the SafeAndConsensual composite mutator
.addMutator('your.custom.MagicMutator') // List of mutators: https://github.com/solven-eu/cleanthat/blob/master/MUTATORS.generated.MD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ public class CleanthatJavaConfig {

private String version = CleanthatJavaStep.defaultVersion();

private String javaparserVersion = CleanthatJavaStep.defaultJavaparserVersion();

private String sourceJdk = CleanthatJavaStep.defaultSourceJdk();

private List<String> mutators = new ArrayList<>(CleanthatJavaStep.defaultMutators());
Expand All @@ -459,6 +461,18 @@ public CleanthatJavaConfig version(String version) {
return this;
}

/**
* Advanced: override the version of JavaParser pulled in transitively by Cleanthat. The coordinate
* {@code com.github.javaparser:javaparser-symbol-solver-core:<version>} is appended to the resolved classpath;
* standard dependency resolution rules then apply (newest wins).
*/
public CleanthatJavaConfig javaparserVersion(String javaparserVersion) {
Objects.requireNonNull(javaparserVersion);
this.javaparserVersion = javaparserVersion;
replaceStep(createStep());
return this;
}

public CleanthatJavaConfig sourceCompatibility(String jdkVersion) {
Objects.requireNonNull(jdkVersion);
this.sourceJdk = jdkVersion;
Expand Down Expand Up @@ -504,6 +518,7 @@ private FormatterStep createStep() {
return CleanthatJavaStep.create(
groupArtifact,
version,
javaparserVersion,
sourceJdk, mutators, excludedMutators, includeDraft, provisioner());
}
}
Expand Down
4 changes: 4 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
- Add `<javaparserVersion>` option to `<cleanthat>`, allowing users to override the JavaParser version pulled in transitively by Cleanthat. ([#2903](https://github.com/diffplug/spotless/pull/2903))
### Changes
- Bump default `cleanthat` version `2.24` -> `2.25`. ([#2903](https://github.com/diffplug/spotless/pull/2903))

## [3.4.0] - 2026-03-18
### Added
Expand Down
3 changes: 2 additions & 1 deletion plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ These mechanisms already exist for the Gradle plugin.

```xml
<cleanthat>
<version>2.8</version> <!-- optional version of Cleanthat -->
<version>2.25</version> <!-- optional version of Cleanthat -->
<javaparserVersion>3.26.4</javaparserVersion> <!-- optional. Advanced: override the JavaParser version pulled in transitively by Cleanthat -->
<sourceJdk>${maven.compiler.source}</sourceJdk> <!-- optional. Default to ${maven.compiler.source} else '1.7' -->
<mutators>
<mutator>SafeAndConsensual</mutator> <!-- optional. Default to 'SafeAndConsensual' to include all mutators -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 DiffPlug
* Copyright 2023-2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,14 @@ public class CleanthatJava implements FormatterStepFactory {
@Parameter
private String version;

/**
* Optional: override the version of JavaParser pulled in as a transitive dependency of Cleanthat. Advanced use-case:
* declaring a version here appends {@code com.github.javaparser:javaparser-symbol-solver-core:<javaparserVersion>}
* to the resolved classpath, so standard Maven resolution rules (newest wins) apply. At your own risk.
*/
@Parameter
private String javaparserVersion;

// https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#source
@Parameter(property = "maven.compiler.source")
private String sourceJdk = CleanthatJavaStep.defaultSourceJdk();
Expand All @@ -49,6 +57,6 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) {
String groupArtifact = this.groupArtifact != null ? this.groupArtifact : CleanthatJavaStep.defaultGroupArtifact();
String version = this.version != null ? this.version : CleanthatJavaStep.defaultVersion();

return CleanthatJavaStep.create(groupArtifact, version, sourceJdk, mutators, excludedMutators, includeDraft, config.getProvisioner());
return CleanthatJavaStep.create(groupArtifact, version, javaparserVersion, sourceJdk, mutators, excludedMutators, includeDraft, config.getProvisioner());
}
}
Loading