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");