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: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]
### Changes
* Bump default `ktfmt` version to latest `0.58` -> `0.59`. ([#2681](https://github.com/diffplug/spotless/pull/2681)
* Use Task Providers for task initialization. [#2719](https://github.com/diffplug/spotless/pull/2719)
* **BREAKING** Bump minimum supported Gradle version from 7.3 to 8.1. [#2719](https://github.com/diffplug/spotless/pull/2719)
### Fixed
- palantirJavaFormat is no longer arbitrarily set to outdated versions on Java 17, latest available version is always used ([#2686](https://github.com/diffplug/spotless/pull/2686) fixes [#2685](https://github.com/diffplug/spotless/issues/2685))
* palantirJavaFormat is no longer arbitrarily set to outdated versions on Java 17, latest available version is always used ([#2686](https://github.com/diffplug/spotless/pull/2686) fixes [#2685](https://github.com/diffplug/spotless/issues/2685))
### Removed
* **BREAKING** Drop support for older Ktlint versions. ([#2711](https://github.com/diffplug/spotless/pull/2711))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ public TaskProvider<SpotlessApply> createIndependentApplyTaskLazy(String taskNam
return spotless.project.getTasks().register(taskName, SpotlessApply.class,
task -> {
task.dependsOn(spotlessTask);
task.init(spotlessTask.get());
task.init(spotlessTask);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.work.DisableCachingByDefault;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -133,10 +134,10 @@ public void visitFile(FileVisitDetails fileVisitDetails) {
abstract Property<String> getProjectPath();

@Override
void init(SpotlessTaskImpl impl) {
void init(TaskProvider<SpotlessTaskImpl> impl) {
super.init(impl);
getProjectPath().set(getProject().getPath());
getEncoding().set(impl.getEncoding());
getEncoding().set(impl.map(SpotlessTask::getEncoding));
getRunToFixMessage().convention(
"Run '" + calculateGradleCommand() + " spotlessApply' to fix all violations.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.UntrackedTask;

import com.diffplug.spotless.Formatter;
Expand All @@ -33,10 +34,10 @@

@UntrackedTask(because = "undeclared inputs/outputs")
public class SpotlessDiagnoseTask extends DefaultTask {
SpotlessTask source;
TaskProvider<? extends SpotlessTask> source;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tasks should not depend on other tasks like this. You should properly model your inputs and outputs between tasks.

For things that are shared between tasks, you should use a build service, for everything else you will need serialize to a file and other task should use that file as an input.

Existing set up is fragile and forces you to use UntrackedTask meaning these tasks will run all the time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't disagree, but SpotlessDiagnoseTask is only used to debug errors in the other tasks. It would never be part of a CI pipeline. Rather than address this tech debt, I think better to just remove the feature


@Internal
public SpotlessTask getSource() {
public TaskProvider<? extends SpotlessTask> getSource() {
return source;
}

Expand All @@ -45,10 +46,10 @@ public SpotlessTask getSource() {
public void performAction() throws IOException {
Path srcRoot = getProject().getProjectDir().toPath();
Path diagnoseRoot = getProject().getLayout().getBuildDirectory().getAsFile().get()
.toPath().resolve("spotless-diagnose-" + source.formatName());
.toPath().resolve("spotless-diagnose-" + source.get().formatName());
getProject().delete(diagnoseRoot.toFile());
try (Formatter formatter = source.buildFormatter()) {
for (File file : source.target) {
try (Formatter formatter = source.get().buildFormatter()) {
for (File file : source.get().target) {
getLogger().debug("Running padded cell check on " + file);
PaddedCell padded = PaddedCell.check(formatter, file);
if (!padded.misbehaved()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,18 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) {

// create the check and apply control tasks
TaskProvider<SpotlessApply> applyTask = tasks.register(taskName + APPLY, SpotlessApply.class, task -> {
task.init(spotlessTask.get());
task.init(spotlessTask);
task.setGroup(TASK_GROUP);
task.setEnabled(ideHook.path == null);
task.dependsOn(spotlessTask);
});
rootApplyTask.configure(task -> task.dependsOn(ideHook.path == null ? applyTask : spotlessTask));

TaskProvider<SpotlessCheck> checkTask = tasks.register(taskName + CHECK, SpotlessCheck.class, task -> {
SpotlessTaskImpl source = spotlessTask.get();
task.setGroup(TASK_GROUP);
task.init(source);
task.init(spotlessTask);
task.setEnabled(ideHook.path == null);
task.dependsOn(source);
task.dependsOn(spotlessTask);

// if the user runs both, make sure that apply happens first,
task.mustRunAfter(applyTask);
Expand All @@ -99,7 +98,7 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) {

// create the diagnose task
TaskProvider<SpotlessDiagnoseTask> diagnoseTask = tasks.register(taskName + DIAGNOSE, SpotlessDiagnoseTask.class, task -> {
task.source = spotlessTask.get();
task.source = spotlessTask;
task.setGroup(TASK_GROUP);
task.mustRunAfter(BasePlugin.CLEAN_TASK_NAME);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

public class SpotlessPlugin implements Plugin<Project> {
static final String SPOTLESS_MODERN = "spotlessModern";
static final String VER_GRADLE_MIN = "7.3";
static final String VER_GRADLE_MIN = "8.1";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried every gradle version between 7.3 and 8.1 and it's the only one that can make all tests pass. Otherwise it fails https://github.com/diffplug/spotless/actions/runs/19336302893/job/55313408204

static final String VER_GRADLE_MIN_VERSION_FOR_CUSTOM = "8.4";
private static final int MINIMUM_JRE = 17;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.gradle.api.services.BuildService;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.tooling.events.FinishEvent;
import org.gradle.tooling.events.OperationCompletionListener;

Expand Down Expand Up @@ -125,12 +126,12 @@ abstract static class ClientTask extends DefaultTask {
@Inject
protected abstract ObjectFactory getConfigCacheWorkaround();

void init(SpotlessTaskImpl impl) {
usesServiceTolerateTestFailure(this, impl.getTaskServiceProvider());
getSpotlessCleanDirectory().set(impl.getCleanDirectory());
getSpotlessLintsDirectory().set(impl.getLintsDirectory());
getTaskService().set(impl.getTaskService());
getProjectDir().set(impl.getProjectDir());
void init(TaskProvider<SpotlessTaskImpl> impl) {
usesServiceTolerateTestFailure(this, impl.flatMap(SpotlessTaskImpl::getTaskServiceProvider));
getSpotlessCleanDirectory().set(impl.map(SpotlessTask::getCleanDirectory));
getSpotlessLintsDirectory().set(impl.map(SpotlessTask::getLintsDirectory));
getTaskService().set(impl.flatMap(SpotlessTask::getTaskService));
getProjectDir().set(impl.flatMap(SpotlessTask::getProjectDir));
}

String sourceTaskPath() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 DiffPlug
* Copyright 2020-2025 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 @@ -24,8 +24,7 @@ public class ConfigurationCacheTest extends GradleIntegrationHarness {
@Override
public GradleRunner gradleRunner() throws IOException {
setFile("gradle.properties").toContent("org.gradle.unsafe.configuration-cache=true");
setFile("settings.gradle").toContent("enableFeaturePreview(\"STABLE_CONFIGURATION_CACHE\")");
return super.gradleRunner().withGradleVersion(GradleVersionSupport.STABLE_CONFIGURATION_CACHE.version);
return super.gradleRunner();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.gradle.api.Project;
import org.gradle.api.provider.Provider;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.api.tasks.TaskProvider;
import org.junit.jupiter.api.Test;

import com.diffplug.common.base.StringPrinter;
Expand All @@ -48,34 +49,30 @@ public BuildServiceParameters.None getParameters() {
});

File file;
SpotlessTaskImpl task;
SpotlessCheck check;
TaskProvider<SpotlessTaskImpl> task;
TaskProvider<SpotlessCheck> check;

Bundle(String name) throws IOException {
file = setFile("src/test." + name).toContent("CCC");
task = createFormatTask(name);
check = createCheckTask(name, task);
createApplyTask(name, task);
task = registerFormatTask(name);
check = registerCheckTask(name, task);
registerApplyTask(name, task);
}

private SpotlessTaskImpl createFormatTask(String name) {
SpotlessTaskImpl task = project.getTasks().create("spotless" + SpotlessPlugin.capitalize(name), SpotlessTaskImpl.class);
task.init(taskService);
task.setLineEndingsPolicy(project.provider(LineEnding.UNIX::createPolicy));
task.setTarget(Collections.singletonList(file));
return task;
private TaskProvider<SpotlessTaskImpl> registerFormatTask(String name) {
return project.getTasks().register("spotless" + SpotlessPlugin.capitalize(name), SpotlessTaskImpl.class, task -> {
task.init(taskService);
task.setLineEndingsPolicy(project.provider(LineEnding.UNIX::createPolicy));
task.setTarget(Collections.singletonList(file));
});
}

private SpotlessCheck createCheckTask(String name, SpotlessTaskImpl source) {
SpotlessCheck task = project.getTasks().create("spotless" + SpotlessPlugin.capitalize(name) + "Check", SpotlessCheck.class);
task.init(source);
return task;
private TaskProvider<SpotlessCheck> registerCheckTask(String name, TaskProvider<SpotlessTaskImpl> source) {
return project.getTasks().register("spotless" + SpotlessPlugin.capitalize(name) + "Check", SpotlessCheck.class, task -> task.init(source));
}

private SpotlessApply createApplyTask(String name, SpotlessTaskImpl source) {
SpotlessApply task = project.getTasks().create("spotless" + SpotlessPlugin.capitalize(name) + "Apply", SpotlessApply.class);
task.init(source);
return task;
private TaskProvider<SpotlessApply> registerApplyTask(String name, TaskProvider<SpotlessTaskImpl> source) {
return project.getTasks().register("spotless" + SpotlessPlugin.capitalize(name) + "Apply", SpotlessApply.class, task -> task.init(source));
}

String checkFailureMsg() {
Expand All @@ -88,8 +85,8 @@ String checkFailureMsg() {
}

void check() throws Exception {
Tasks.execute(task);
check.performActionTest();
Tasks.execute(task.get());
check.get().performActionTest();
}
}

Expand All @@ -99,8 +96,8 @@ private Bundle create(File... files) throws IOException {

private Bundle create(List<File> files) throws IOException {
Bundle bundle = new Bundle("underTest");
bundle.task.setLineEndingsPolicy(bundle.project.provider(LineEnding.UNIX::createPolicy));
bundle.task.setTarget(files);
bundle.task.get().setLineEndingsPolicy(bundle.project.provider(LineEnding.UNIX::createPolicy));
bundle.task.get().setTarget(files);
return bundle;
}

Expand Down Expand Up @@ -138,7 +135,7 @@ void lineEndingProblem() throws Exception {
void customRunToFixMessage() throws Exception {
Bundle task = create(setFile("testFile").toContent("A\r\nB\r\nC\r\n"));
String customMessage = "Formatting issues detected, please read automatic-code-formatting.txt and correct.";
task.check.getRunToFixMessage().set(customMessage);
task.check.get().getRunToFixMessage().set(customMessage);

String msg = task.checkFailureMsg();

Expand All @@ -150,7 +147,7 @@ void customRunToFixMessage() throws Exception {
@Test
void whitespaceProblem() throws Exception {
Bundle spotless = create(setFile("testFile").toContent("A \nB\t\nC \n"));
spotless.task.setSteps(List.of(TrimTrailingWhitespaceStep.create()));
spotless.task.get().setSteps(List.of(TrimTrailingWhitespaceStep.create()));
assertCheckFailure(spotless,
" testFile",
" @@ -1,3 +1,3 @@",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ public class GradleIntegrationHarness extends ResourceHarness {
public enum GradleVersionSupport {
MINIMUM(SpotlessPlugin.VER_GRADLE_MIN),

// https://docs.gradle.org/7.5/userguide/configuration_cache.html#config_cache:stable
STABLE_CONFIGURATION_CACHE("7.5"),

CUSTOM_STEPS(SpotlessPlugin.VER_GRADLE_MIN_VERSION_FOR_CUSTOM),

;
Expand All @@ -59,7 +56,8 @@ public enum GradleVersionSupport {
String minVersionForRunningJRE;
switch (Jvm.version()) {
case 25:
// TODO: https://docs.gradle.org/current/userguide/compatibility.html
minVersionForRunningJRE = "9.1.0";
break;
case 24:
minVersionForRunningJRE = "8.14";
break;
Expand All @@ -75,12 +73,6 @@ public enum GradleVersionSupport {
case 20:
minVersionForRunningJRE = "8.3";
break;
case 19:
minVersionForRunningJRE = "7.6";
break;
case 18:
minVersionForRunningJRE = "7.5";
break;
default:
minVersionForRunningJRE = null;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ private void runWith(boolean configurationCache, String... arguments) throws IOE
protected GradleRunner gradleRunner(boolean configurationCache) throws IOException {
if (configurationCache) {
setFile("gradle.properties").toContent("org.gradle.unsafe.configuration-cache=true");
setFile("settings.gradle").toContent("enableFeaturePreview(\"STABLE_CONFIGURATION_CACHE\")");
return super.gradleRunner().withGradleVersion(GradleVersionSupport.STABLE_CONFIGURATION_CACHE.version);
return super.gradleRunner();
} else {
File gradleProps = new File(rootFolder(), "gradle.properties");
if (gradleProps.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,7 @@ void useNpmNextToConfiguredNodePluginFromNodeGradlePlugin() throws Exception {
public void supportsConfigurationCache() throws Exception {
setFile("build.gradle").toResource("com/diffplug/gradle/spotless/NpmTestsWithoutNpmInstallationTest_gradle_node_plugin_example_1.gradle");
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
BuildResult spotlessApply = gradleRunner()
.withGradleVersion(GradleVersionSupport.STABLE_CONFIGURATION_CACHE.version)
.withArguments("--stacktrace", "--configuration-cache", "spotlessApply").build();
BuildResult spotlessApply = gradleRunner().withArguments("--stacktrace", "--configuration-cache", "spotlessApply").build();
Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL");
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_2.clean");
}
Expand Down
Loading
Loading