diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index b73e607579..7b24b9ae89 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
## [Unreleased]
+### Added
+- Partial support for isolated projects. They work if predeclared dependencies are not used. ([#2854](https://github.com/diffplug/spotless/pull/2854))
### Fixed
- Fix the ability to specify a wildcard version (`*`) for external formatter executables, which did not work. ([#2848](https://github.com/diffplug/spotless/pull/2848))
diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md
index d07316069b..07bb302af5 100644
--- a/plugin-gradle/README.md
+++ b/plugin-gradle/README.md
@@ -1918,6 +1918,8 @@ Alternatively, you can also use `predeclareDepsFromBuildscript()` to resolve the
If you use this feature, you will get an error if you use a formatter in a subproject which is not declared in the `spotlessPredeclare` block.
+Note that this feature is also incompatible with Isolated projects, because every project must reference the root project.
+
## How do I preview what `spotlessApply` will do?
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/BaseKotlinExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/BaseKotlinExtension.java
index 975be992c2..179739aa58 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/BaseKotlinExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/BaseKotlinExtension.java
@@ -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.
@@ -160,7 +160,7 @@ private KtlintConfig(
Map editorConfigOverride,
List customRuleSets) throws IOException {
Objects.requireNonNull(version);
- File defaultEditorConfig = getProject().getRootProject().file(".editorconfig");
+ File defaultEditorConfig = new File(getProject().getRootDir(), ".editorconfig");
FileSignature editorConfigPath = defaultEditorConfig.exists() ? FileSignature.signAsList(defaultEditorConfig) : null;
this.version = version;
this.editorConfigPath = editorConfigPath;
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index 913f320d73..02a3bbf3b1 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -95,11 +95,11 @@ public FormatExtension(SpotlessExtension spotless) {
}
protected final Provisioner provisioner() {
- return spotless.getRegisterDependenciesTask().getTaskService().get().provisionerFor(spotless);
+ return spotless.getSpotlessTaskService().get().provisionerFor(spotless);
}
protected final P2Provisioner p2Provisioner() {
- return spotless.getRegisterDependenciesTask().getTaskService().get().p2ProvisionerFor(spotless);
+ return spotless.getSpotlessTaskService().get().p2ProvisionerFor(spotless);
}
private String formatName() {
@@ -635,7 +635,8 @@ public LicenseHeaderConfig updateYearWithLatest(boolean updateYearWithLatest) {
FormatterStep createStep() {
return builder.withYearModeLazy(() -> {
- if (Boolean.parseBoolean(GradleCompat.findOptionalProperty(spotless.project, LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()))) {
+ String yearProperty = spotless.project.getProviders().gradleProperty(LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()).getOrNull();
+ if (Boolean.parseBoolean(yearProperty)) {
return YearMode.SET_FROM_GIT;
} else {
boolean updateYear = updateYearWithLatest == null ? getRatchetFrom() != null : updateYearWithLatest;
@@ -1098,7 +1099,7 @@ protected void setupTask(SpotlessTask task) {
LineEnding lineEndings = getLineEndings();
task.setLineEndingsPolicy(
getProject().provider(() -> lineEndings.createPolicy(projectDir.getAsFile(), () -> totalTarget)));
- spotless.getRegisterDependenciesTask().hookSubprojectTask(task);
+ spotless.getSpotlessTaskService().get().hookSubprojectTask(getProject(), task);
task.setupRatchet(getRatchetFrom() != null ? getRatchetFrom() : "");
}
@@ -1134,7 +1135,7 @@ public TaskProvider createIndependentApplyTaskLazy(String taskNam
"Task name must not end with " + SpotlessExtension.APPLY);
TaskProvider spotlessTask = spotless.project.getTasks()
.register(taskName + SpotlessTaskService.INDEPENDENT_HELPER, SpotlessTaskImpl.class, task -> {
- task.init(spotless.getRegisterDependenciesTask().getTaskService());
+ task.init(spotless.getSpotlessTaskService());
setupTask(task);
// clean removes the SpotlessCache, so we have to run after clean
task.mustRunAfter(BasePlugin.CLEAN_TASK_NAME);
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GradleCompat.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GradleCompat.java
deleted file mode 100644
index 16d02b75b8..0000000000
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GradleCompat.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2025 DiffPlug
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.diffplug.gradle.spotless;
-
-import javax.annotation.Nullable;
-
-import org.gradle.api.Project;
-
-public final class GradleCompat {
- private GradleCompat() {}
-
- @Nullable public static String findOptionalProperty(Project project, String propertyName) {
- @Nullable String value = project.getProviders().gradleProperty(propertyName).getOrNull();
- if (value != null) {
- return value;
- }
- @Nullable Object property = project.findProperty(propertyName);
- if (property != null) {
- return property.toString();
- }
- return null;
- }
-
- public static boolean isPropertyPresent(Project project, String propertyName) {
- return project.getProviders().gradleProperty(propertyName).isPresent() ||
- project.hasProperty(propertyName);
- }
-}
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java
index 8a10ffbcf3..6090bd748f 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/IdeHook.java
@@ -39,10 +39,10 @@ static class State extends NoLambda.EqualityBasedOnSerialization {
final boolean useStdOut;
State(Project project) {
- var pathsString = GradleCompat.findOptionalProperty(project, PROPERTY);
+ var pathsString = project.getProviders().gradleProperty(PROPERTY).getOrNull();
if (pathsString != null) {
- useStdIn = GradleCompat.isPropertyPresent(project, USE_STD_IN);
- useStdOut = GradleCompat.isPropertyPresent(project, USE_STD_OUT);
+ useStdIn = project.getProviders().gradleProperty(USE_STD_IN).isPresent();
+ useStdOut = project.getProviders().gradleProperty(USE_STD_OUT).isPresent();
paths = Arrays.stream(pathsString.split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/RegisterDependenciesTask.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/RegisterDependenciesTask.java
index 33aded8bdd..3c66f5427f 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/RegisterDependenciesTask.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/RegisterDependenciesTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2023 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.
@@ -25,7 +25,6 @@
import org.gradle.api.DefaultTask;
import org.gradle.api.provider.Provider;
-import org.gradle.api.services.BuildServiceRegistry;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.OutputFile;
@@ -64,8 +63,7 @@ void hookSubprojectTask(SpotlessTask task) {
void setup() {
Preconditions.checkArgument(getProject().getRootProject() == getProject(), "Can only be used on the root project");
String compositeBuildSuffix = getName().substring(TASK_NAME.length()); // see https://github.com/diffplug/spotless/pull/1001
- BuildServiceRegistry buildServices = getProject().getGradle().getSharedServices();
- taskService = buildServices.registerIfAbsent("SpotlessTaskService" + compositeBuildSuffix, SpotlessTaskService.class, spec -> {});
+ taskService = SpotlessTaskService.registerIfAbsent(getProject(), compositeBuildSuffix);
usesService(taskService);
getBuildEventsListenerRegistry().onTaskCompletion(taskService);
unitOutput = new File(getProject().getLayout().getBuildDirectory().getAsFile().get(), "tmp/spotless-register-dependencies");
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
index 2ff4896d9e..c41b28c331 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java
@@ -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.
@@ -27,15 +27,14 @@
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
-import org.gradle.api.tasks.TaskContainer;
-import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.provider.Provider;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
import com.diffplug.spotless.LineEnding;
public abstract class SpotlessExtension {
final Project project;
- private final RegisterDependenciesTask registerDependenciesTask;
+ private final Provider spotlessTaskService;
protected static final String TASK_GROUP = LifecycleBasePlugin.VERIFICATION_GROUP;
protected static final String BUILD_SETUP_TASK_GROUP = "build setup";
@@ -52,11 +51,11 @@ public abstract class SpotlessExtension {
protected SpotlessExtension(Project project) {
this.project = requireNonNull(project);
- this.registerDependenciesTask = findRegisterDepsTask().get();
+ this.spotlessTaskService = SpotlessTaskService.registerIfAbsent(project, "");
}
- RegisterDependenciesTask getRegisterDependenciesTask() {
- return registerDependenciesTask;
+ Provider getSpotlessTaskService() {
+ return spotlessTaskService;
}
/** Line endings (if any). */
@@ -303,27 +302,6 @@ T instantiateFormatExtension(Class clazz) {
protected abstract void createFormatTasks(String name, FormatExtension formatExtension);
- TaskProvider findRegisterDepsTask() {
- try {
- return findRegisterDepsTask(RegisterDependenciesTask.TASK_NAME);
- } catch (Exception e) {
- // in a composite build there can be multiple Spotless plugins on the classpath, and they will each try to register
- // a task on the root project with the same name. That will generate casting errors, which we can catch and try again
- // with an identity-specific identifier.
- // https://github.com/diffplug/spotless/pull/1001 for details
- return findRegisterDepsTask(RegisterDependenciesTask.TASK_NAME + System.identityHashCode(RegisterDependenciesTask.class));
- }
- }
-
- private TaskProvider findRegisterDepsTask(String taskName) {
- TaskContainer rootProjectTasks = project.getRootProject().getTasks();
- if (!rootProjectTasks.getNames().contains(taskName)) {
- return rootProjectTasks.register(taskName, RegisterDependenciesTask.class, RegisterDependenciesTask::setup);
- } else {
- return rootProjectTasks.named(taskName, RegisterDependenciesTask.class);
- }
- }
-
public void predeclareDepsFromBuildscript() {
if (project.getRootProject() != project) {
throw new GradleException("predeclareDepsFromBuildscript can only be called from the root project");
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java
index 04bfb8d221..173b5a1113 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionImpl.java
@@ -61,7 +61,7 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) {
// create the SpotlessTask
String taskName = EXTENSION + SpotlessPlugin.capitalize(name);
TaskProvider spotlessTask = tasks.register(taskName, SpotlessTaskImpl.class, task -> {
- task.init(getRegisterDependenciesTask().getTaskService());
+ task.init(getSpotlessTaskService());
task.setGroup(TASK_GROUP);
task.getIdeHookState().set(ideHook);
// clean removes the SpotlessCache, so we have to run after clean
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionPredeclare.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionPredeclare.java
index 52a40a22b4..3357f19c12 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionPredeclare.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionPredeclare.java
@@ -20,23 +20,28 @@
import org.gradle.api.Action;
import org.gradle.api.Project;
+import org.gradle.api.tasks.TaskProvider;
import com.diffplug.spotless.LazyForwardingEquality;
public class SpotlessExtensionPredeclare extends SpotlessExtension {
private final SortedMap toSetup = new TreeMap<>();
+ private final RegisterDependenciesTask registerDependenciesTask;
public SpotlessExtensionPredeclare(Project project, GradleProvisioner.Policy policy) {
super(project);
- getRegisterDependenciesTask().getTaskService().get().predeclaredProvisioner = policy.dedupingProvisioner(project);
- getRegisterDependenciesTask().getTaskService().get().predeclaredP2Provisioner = policy.dedupingP2Provisioner(project);
+ this.registerDependenciesTask = findRegisterDepsTask().get();
+ SpotlessTaskService taskService = getSpotlessTaskService().get();
+ taskService.isUsingPredeclared = true;
+ taskService.predeclaredProvisioner = policy.dedupingProvisioner(project);
+ taskService.predeclaredP2Provisioner = policy.dedupingP2Provisioner(project);
project.afterEvaluate(unused -> toSetup.forEach((name, formatExtension) -> {
for (Action lazyAction : formatExtension.lazyActions) {
lazyAction.execute(formatExtension);
}
- getRegisterDependenciesTask().steps.addAll(formatExtension.steps);
+ registerDependenciesTask.steps.addAll(formatExtension.steps);
// needed to fix Deemon memory leaks (#1194), but this line came from https://github.com/diffplug/spotless/pull/1206
- LazyForwardingEquality.unlazy(getRegisterDependenciesTask().steps);
+ LazyForwardingEquality.unlazy(registerDependenciesTask.steps);
}));
}
@@ -49,4 +54,21 @@ protected void createFormatTasks(String name, FormatExtension formatExtension) {
protected void predeclare(GradleProvisioner.Policy policy) {
throw new UnsupportedOperationException("predeclare can't be called from within `" + EXTENSION_PREDECLARE + "`");
}
+
+ private TaskProvider findRegisterDepsTask() {
+ try {
+ return findRegisterDepsTask(RegisterDependenciesTask.TASK_NAME);
+ } catch (Exception e) {
+ // in a composite build there can be multiple Spotless plugins on the classpath, and they will each try to register
+ // a task on the root project with the same name. That will generate casting errors, which we can catch and try again
+ // with an identity-specific identifier.
+ // https://github.com/diffplug/spotless/pull/1001 for details
+ return findRegisterDepsTask(RegisterDependenciesTask.TASK_NAME + System.identityHashCode(RegisterDependenciesTask.class));
+ }
+ }
+
+ private TaskProvider findRegisterDepsTask(String taskName) {
+ return project.getTasks().register(taskName, RegisterDependenciesTask.class, RegisterDependenciesTask::setup);
+ }
+
}
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java
index 2bd773f2d3..1583cf3d67 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessPlugin.java
@@ -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.
@@ -42,7 +42,7 @@ public void apply(Project project) {
+ "https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_cross_compilation");
}
// if -PspotlessModern=true, then use the modern stuff instead of the legacy stuff
- if (GradleCompat.isPropertyPresent(project, SPOTLESS_MODERN)) {
+ if (project.getProviders().gradleProperty(SPOTLESS_MODERN).isPresent()) {
project.getLogger().warn("'spotlessModern' has no effect as of Spotless 5.0, recommend removing it.");
}
// make sure there's a `clean` and a `check`
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTaskService.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTaskService.java
index 3632f74050..5538417ba5 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTaskService.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTaskService.java
@@ -28,6 +28,7 @@
import javax.inject.Inject;
import org.gradle.api.DefaultTask;
+import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileTree;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileVisitDetails;
@@ -55,6 +56,7 @@
* apply already did).
*/
public abstract class SpotlessTaskService implements BuildService, AutoCloseable, OperationCompletionListener {
+ protected boolean isUsingPredeclared = false;
private final Map apply = Collections.synchronizedMap(new HashMap<>());
private final Map source = Collections.synchronizedMap(new HashMap<>());
private final Map provisioner = Collections.synchronizedMap(new HashMap<>());
@@ -126,6 +128,21 @@ static void usesServiceTolerateTestFailure(DefaultTask task, Provider {
+ registerTask.hookSubprojectTask(task);
+ });
+ }
+
+ public static Provider registerIfAbsent(Project project, String suffix) {
+ return project.getGradle().getSharedServices()
+ .registerIfAbsent("SpotlessTaskService" + suffix, SpotlessTaskService.class, spec -> {});
+ }
+
abstract static class ClientTask extends DefaultTask {
@Internal
abstract Property getSpotlessCleanDirectory();
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrowTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrowTest.java
index ebd4bcbbf2..3e71cfc984 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrowTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/ErrorShouldRethrowTest.java
@@ -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.
@@ -136,10 +136,9 @@ private void expectSuccess() throws Exception {
private StringSelfie expectFailureAndConsoleToBe() throws Exception {
BuildResult result = gradleRunner().withArguments("check").buildAndFail();
String output = result.getOutput();
- int register = output.indexOf(":spotlessInternalRegisterDependencies");
- int firstNewlineAfterThat = output.indexOf('\n', register + 1);
+ int firstTask = output.indexOf("> Task");
int firstTry = output.indexOf("\n* Try:");
- String useThisToMatch = output.substring(firstNewlineAfterThat, firstTry).trim();
+ String useThisToMatch = output.substring(firstTask, firstTry).trim();
return Selfie.expectSelfie(useThisToMatch);
}
}
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationHarness.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationHarness.java
index 2882e21b4f..0e223a3409 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationHarness.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationHarness.java
@@ -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.
@@ -197,7 +197,7 @@ private void taskIsUpToDate(String task, boolean upToDate) throws IOException {
List expected = outcomes(buildResult, upToDate ? TaskOutcome.UP_TO_DATE : TaskOutcome.SUCCESS);
List notExpected = outcomes(buildResult, upToDate ? TaskOutcome.SUCCESS : TaskOutcome.UP_TO_DATE);
- boolean everythingAsExpected = !expected.isEmpty() && notExpected.isEmpty() && buildResult.getTasks().size() - 1 == expected.size();
+ boolean everythingAsExpected = !expected.isEmpty() && notExpected.isEmpty() && buildResult.getTasks().size() == expected.size();
if (!everythingAsExpected) {
fail("Expected all tasks to be " + (upToDate ? TaskOutcome.UP_TO_DATE : TaskOutcome.SUCCESS) + ", but instead was\n" + buildResultToString(buildResult));
}
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/MultiProjectTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/MultiProjectTest.java
index 69301327c7..b9ffd83a50 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/MultiProjectTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/MultiProjectTest.java
@@ -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.
@@ -151,4 +151,40 @@ public void predeclaredUndeclared() throws IOException {
Assertions.assertThat(gradleRunner().withArguments("spotlessApply").buildAndFail().getOutput())
.contains("Could not find method spotlessPredeclare() for arguments");
}
+
+ @Test
+ void nonPredeclaredSupportsIsolatedProjects() throws IOException {
+ setFile("gradle.properties").toContent("org.gradle.unsafe.isolated-projects=true");
+ setFile("build.gradle").toLines(
+ "plugins {",
+ " id 'com.diffplug.spotless'",
+ "}",
+ "repositories { mavenCentral() }",
+ "",
+ "spotless {",
+ " java {",
+ " target file('test.java')",
+ " googleJavaFormat('1.17.0')",
+ " }",
+ "}");
+ createNSubprojects();
+ gradleRunner().withArguments("spotlessApply").build();
+ }
+
+ @Test
+ void predeclaredRequiresNonIsolatedProjects() throws IOException {
+ setFile("gradle.properties").toContent("org.gradle.unsafe.isolated-projects=true");
+ setFile("build.gradle").toLines(
+ "plugins {",
+ " id 'com.diffplug.spotless'",
+ "}",
+ "repositories { mavenCentral() }",
+ "spotless { predeclareDeps() }",
+ "spotlessPredeclare {",
+ " java { googleJavaFormat('1.17.0') }",
+ "}");
+ createNSubprojects();
+ Assertions.assertThat(gradleRunner().withArguments("spotlessApply").buildAndFail().getOutput())
+ .containsAnyOf("Cannot access project", "cannot access 'Project.tasks'");
+ }
}
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/RegisterDependenciesTaskTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/RegisterDependenciesTaskTest.java
index 76d0449060..92d6ed179d 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/RegisterDependenciesTaskTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/RegisterDependenciesTaskTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2023 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.
@@ -43,8 +43,6 @@ void duplicateConfigs() throws IOException {
setFile("gradle.properties").toLines();
String newestSupported = gradleRunner().withArguments("spotlessCheck").build().getOutput();
Assertions.assertThat(newestSupported.replace("\r", ""))
- .startsWith(
- "> Task :spotlessInternalRegisterDependencies\n")
.contains(
"> Task :sub:spotlessJava\n",
"> Task :sub:spotlessJavaCheck\n",
diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/UpToDateTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/UpToDateTest.java
index 9b7eccdfff..1c06374e9f 100644
--- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/UpToDateTest.java
+++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/UpToDateTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2021 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.
@@ -88,7 +88,7 @@ void testPathologicalCase() throws IOException {
// the format task is UP-TO-DATE (same inputs), but the apply tasks will run again
pauseForFilesystem();
BuildResult buildResult = gradleRunner().withArguments("spotlessApply").build();
- Assertions.assertThat(buildResult.taskPaths(TaskOutcome.UP_TO_DATE)).containsExactly(":spotlessInternalRegisterDependencies", ":spotlessMisc");
+ Assertions.assertThat(buildResult.taskPaths(TaskOutcome.UP_TO_DATE)).containsExactly(":spotlessMisc");
Assertions.assertThat(buildResult.taskPaths(TaskOutcome.SUCCESS)).containsExactly(":spotlessMiscApply", ":spotlessApply");
assertFile("README.md").hasContent("abc");