From e28c8282d9c9a1fd3f07e1254b4f56e7657e84b4 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:10:29 -0400 Subject: [PATCH 01/19] Add Mockito extension for JUnit 5 Signed-off-by: Daniel Lacasse --- subprojects/gradle-plugin-development/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/subprojects/gradle-plugin-development/build.gradle b/subprojects/gradle-plugin-development/build.gradle index 43ca1aea..a01d63c2 100644 --- a/subprojects/gradle-plugin-development/build.gradle +++ b/subprojects/gradle-plugin-development/build.gradle @@ -102,6 +102,7 @@ test { runtimeOnly "org.junit.vintage:junit-vintage-engine:5.8.2" implementation "org.hamcrest:hamcrest:2.2" implementation "org.mockito:mockito-core:4.2.0" + implementation "org.mockito:mockito-junit-jupiter:4.2.0" } testTasks.configureEach { useJUnitPlatform() } } From 0b2a58d055b6313f80b2e2ca0b528bfcda410940 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:16:46 -0400 Subject: [PATCH 02/19] Convert GradlePluginDevelopmentUtils#sourceSets Signed-off-by: Daniel Lacasse --- ...adlePluginDevelopmentTestSuiteFactory.java | 12 ++--- .../GradlePluginDevelopmentPlugin.java | 6 +-- .../util/GradlePluginDevelopmentUtils.java | 5 -- .../internal/util/SourceSetUtils.java | 22 +++++++++ ...leDevelPluginAppliedIntegrationTester.java | 4 +- ...SuiteFinalizeComponentIntegrationTest.java | 6 +-- ...eJavaBasePluginAppliedIntegrationTest.java | 17 ++++--- ...tMetadataConfigurationIntegrationTest.java | 5 +- ...ceSetUtils_SourceSetsIntegrationTests.java | 49 +++++++++++++++++++ 9 files changed, 93 insertions(+), 33 deletions(-) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_SourceSetsIntegrationTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java index 56cb9163..e5d4b70e 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java @@ -19,7 +19,7 @@ import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; final class DefaultGradlePluginDevelopmentTestSuiteFactory implements GradlePluginDevelopmentTestSuiteFactory { private final Project project; @@ -33,13 +33,9 @@ public GradlePluginDevelopmentTestSuite create(String name) { val result = project.getObjects().newInstance(GradlePluginDevelopmentTestSuiteInternal.class, name, project, minimumGradleVersion(project), gradleDistributions()); // Register as finalized action because it adds configuration which early finalize source set property result.whenFinalized(new ConfigurePluginUnderTestMetadataTask(project)); - result.getSourceSet().convention(project.provider(() -> { - if (project.getPluginManager().hasPlugin("java-base")) { - return sourceSets(project).maybeCreate(name); - } else { - throw new RuntimeException("Please apply 'java-base' plugin."); - } - })); + result.getSourceSet().convention(sourceSets(project).map(it -> it.maybeCreate(name)).orElse(project.provider(() -> { + throw new RuntimeException("Please apply 'java-base' plugin."); + }))); result.getTestedSourceSet().convention(project.provider(() -> { if (project.getPluginManager().hasPlugin("java-gradle-plugin")) { return gradlePlugin(project).getPluginSourceSet(); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentPlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentPlugin.java index 7ab97635..0171952f 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentPlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentPlugin.java @@ -17,7 +17,7 @@ import java.util.Arrays; import java.util.List; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; public abstract class GradlePluginDevelopmentPlugin implements Plugin { private static final Logger LOGGER = Logging.getLogger(GradlePluginDevelopmentPlugin.class); @@ -111,7 +111,7 @@ private static boolean hasGroovyLanguageCapability(Project project) { } private static boolean hasGroovySources(Project project) { - SourceSet sourceSet = sourceSets(project).getByName("main"); + SourceSet sourceSet = sourceSets(project).map(it -> it.getByName("main")).get(); GroovySourceSet groovySourceSet = new DslObject(sourceSet).getConvention().findPlugin(GroovySourceSet.class); if (groovySourceSet == null) { return false; @@ -120,7 +120,7 @@ private static boolean hasGroovySources(Project project) { } private static boolean hasJavaSources(Project project) { - SourceSet sourceSet = sourceSets(project).getByName("main"); + SourceSet sourceSet = sourceSets(project).map(it -> it.getByName("main")).get(); return sourceSet.getAllJava().getSrcDirs().stream().anyMatch(File::exists); } diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java index 5f10122d..1f09cd4b 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java @@ -2,7 +2,6 @@ import org.gradle.api.Project; import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.tasks.SourceSetContainer; import org.gradle.plugin.devel.GradlePluginDevelopmentExtension; public final class GradlePluginDevelopmentUtils { @@ -13,8 +12,4 @@ public static GradlePluginDevelopmentExtension gradlePlugin(Project project) { public static JavaPluginExtension java(Project project) { return project.getExtensions().getByType(JavaPluginExtension.class); } - - public static SourceSetContainer sourceSets(Project project) { - return project.getExtensions().getByType(SourceSetContainer.class); - } } diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java new file mode 100644 index 00000000..59238865 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java @@ -0,0 +1,22 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; + +/** + * Additional helper methods for {@link SourceSet}. + */ +public final class SourceSetUtils { + private SourceSetUtils() {} + + public static void sourceSets(Project project, Action action) { + project.getExtensions().configure("sourceSets", action); + } + + public static Provider sourceSets(Project project) { + return project.provider(() -> (SourceSetContainer) project.getExtensions().findByName("sourceSets")); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCoreGradleDevelPluginAppliedIntegrationTester.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCoreGradleDevelPluginAppliedIntegrationTester.java index 54daaad7..b926260d 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCoreGradleDevelPluginAppliedIntegrationTester.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCoreGradleDevelPluginAppliedIntegrationTester.java @@ -8,7 +8,7 @@ import static dev.gradleplugins.ProjectMatchers.named; import static dev.gradleplugins.ProjectMatchers.providerOf; import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; import static org.hamcrest.MatcherAssert.assertThat; public interface GradlePluginDevelopmentTestSuiteCoreGradleDevelPluginAppliedIntegrationTester { @@ -27,7 +27,7 @@ default void hasMainSourceSetAsTestedSourceSetConvention() { @Test default void usesDevelPluginSourceSetAsTestedSourceSetConvention() { - gradlePlugin(project()).pluginSourceSet(sourceSets(project()).create("anotherMain")); + gradlePlugin(project()).pluginSourceSet(sourceSets(project()).map(it -> it.maybeCreate("anotherMain")).get()); assertThat(subject().getTestedSourceSet().value((SourceSet) null), providerOf(named("anotherMain"))); } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteFinalizeComponentIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteFinalizeComponentIntegrationTest.java index aefdb0f4..d9dbf5cb 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteFinalizeComponentIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteFinalizeComponentIntegrationTest.java @@ -1,13 +1,11 @@ package dev.gradleplugins; import org.gradle.api.Project; -import org.gradle.api.tasks.SourceSet; import org.gradle.testfixtures.ProjectBuilder; import org.junit.jupiter.api.BeforeEach; import static dev.gradleplugins.GradlePluginDevelopmentTestSuiteFactory.forProject; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; -import static org.mockito.Mockito.mock; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; class GradlePluginDevelopmentTestSuiteFinalizeComponentIntegrationTest implements GradlePluginDevelopmentTestSuiteFinalizedIntegrationTester { private final Project project = ProjectBuilder.builder().build(); @@ -22,7 +20,7 @@ public GradlePluginDevelopmentTestSuite subject() { @BeforeEach void finalizeTestSuite() { project.getPluginManager().apply("java-base"); - subject.getSourceSet().set(sourceSets(project).create("leek")); + subject.getSourceSet().set(sourceSets(project).map(it -> it.maybeCreate("leek"))); subject.finalizeComponent(); } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteJavaBasePluginAppliedIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteJavaBasePluginAppliedIntegrationTest.java index fbb8f8b2..0e093a4a 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteJavaBasePluginAppliedIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteJavaBasePluginAppliedIntegrationTest.java @@ -8,7 +8,8 @@ import static dev.gradleplugins.GradlePluginDevelopmentTestSuiteFactory.forProject; import static dev.gradleplugins.ProjectMatchers.named; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.not; @@ -26,32 +27,32 @@ void applyJavaBasePlugin() { @Test void createsDefaultSourceSetOnFinalize() { subject.finalizeComponent(); - assertThat(sourceSets(project), hasItem(named("loke"))); + assertThat(sourceSets(project), providerOf(hasItem(named("loke")))); } @Test void createsDefaultSourceSetOnSourceSetPropertyQueryOfConvention() { subject.getSourceSet().set((SourceSet) null); assertThat(subject.getSourceSet().get(), named("loke")); - assertThat(sourceSets(project), hasItem(named("loke"))); + assertThat(sourceSets(project), providerOf(hasItem(named("loke")))); } @Test void doesNotCreateDefaultSourceSetOnFinalizeWhenSourceSetPropertyOverridden() { - subject.getSourceSet().set(sourceSets(project).create("kiel")); + subject.getSourceSet().set(sourceSets(project).map(it -> it.maybeCreate("kiel"))); subject.finalizeComponent(); - assertThat(sourceSets(project), not(hasItem(named("loke")))); + assertThat(sourceSets(project), providerOf(not(hasItem(named("loke"))))); } @Test void doesNotCreateDefaultSourceSetOnSourceSetPropertyQueryWhenSourceSetPropertyOverridden() { - subject.getSourceSet().set(sourceSets(project).create("lope")); + subject.getSourceSet().set(sourceSets(project).map(it -> it.maybeCreate("lope"))); assertThat(subject.getSourceSet().get(), named("lope")); - assertThat(sourceSets(project), not(hasItem(named("loke")))); + assertThat(sourceSets(project), providerOf(not(hasItem(named("loke"))))); } @Test void doesNotCreateDefaultSourceSetOnTestSuiteCreation() { - assertThat(sourceSets(project), not(hasItem(named("loke")))); + assertThat(sourceSets(project), providerOf(not(hasItem(named("loke"))))); } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuitePluginUnderTestMetadataConfigurationIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuitePluginUnderTestMetadataConfigurationIntegrationTest.java index 4dce6371..c3738e4f 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuitePluginUnderTestMetadataConfigurationIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuitePluginUnderTestMetadataConfigurationIntegrationTest.java @@ -4,7 +4,6 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.attributes.Usage; import org.gradle.api.tasks.SourceSet; -import org.gradle.plugin.devel.tasks.PluginUnderTestMetadata; import org.gradle.testfixtures.ProjectBuilder; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -13,7 +12,7 @@ import static dev.gradleplugins.GradlePluginDevelopmentTestSuiteFactory.forProject; import static dev.gradleplugins.ProjectMatchers.coordinate; import static dev.gradleplugins.ProjectMatchers.named; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.sourceSets; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; import static org.hamcrest.CoreMatchers.everyItem; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.MatcherAssert.assertThat; @@ -33,7 +32,7 @@ class GradlePluginDevelopmentTestSuitePluginUnderTestMetadataConfigurationIntegr void configureSourceSet() { project.setGroup("com.example"); project.getPluginManager().apply("java-base"); - subject.getSourceSet().set(sourceSets(project).create("koli")); + subject.getSourceSet().set(sourceSets(project).map(it -> it.maybeCreate("koli"))); } @Test diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_SourceSetsIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_SourceSetsIntegrationTests.java new file mode 100644 index 00000000..9352f95b --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_SourceSetsIntegrationTests.java @@ -0,0 +1,49 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static dev.gradleplugins.ProjectMatchers.absentProvider; +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static org.hamcrest.MatcherAssert.assertThat; + +@ExtendWith(MockitoExtension.class) +class SourceSetUtils_SourceSetsIntegrationTests { + Project project = ProjectBuilder.builder().build(); + @Mock Action action; + + @Nested + class HasSourceSetContainerTest { + @Mock SourceSetContainer sourceSets; + + @BeforeEach + void configureProject() { + project.getExtensions().add("sourceSets", sourceSets); + } + + @Test + void callsActionWithSourceSetContainer() { + SourceSetUtils.sourceSets(project, action); + Mockito.verify(action).execute(sourceSets); + } + + @Test + void returnsProviderOfSourceSetContainer() { + assertThat(SourceSetUtils.sourceSets(project), providerOf(sourceSets)); + } + } + + @Test + void returnsAbsentProviderWhenNoSourceSetContainerExtension() { + assertThat(SourceSetUtils.sourceSets(project), absentProvider()); + } +} From a279b7966a4fa14ad1148a79d372e989f669fb8d Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:18:06 -0400 Subject: [PATCH 03/19] Introduce SourceSetUtils#isMain() helper method Signed-off-by: Daniel Lacasse --- .../internal/util/SourceSetUtils.java | 4 +++ .../util/SourceSetUtils_IsMainTests.java | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_IsMainTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java index 59238865..0c54e4f8 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java @@ -12,6 +12,10 @@ public final class SourceSetUtils { private SourceSetUtils() {} + public static boolean isMain(SourceSet self) { + return self.getName().equals("main"); + } + public static void sourceSets(Project project, Action action) { project.getExtensions().configure("sourceSets", action); } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_IsMainTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_IsMainTests.java new file mode 100644 index 00000000..44b590d3 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_IsMainTests.java @@ -0,0 +1,28 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.tasks.SourceSet; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@ExtendWith(MockitoExtension.class) +class SourceSetUtils_IsMainTests { + @Mock SourceSet subject; + + @Test + void returnsTrueWhenSourceSetNameIsMain() { + Mockito.when(subject.getName()).thenReturn("main"); + assertThat(SourceSetUtils.isMain(subject), is(true)); + } + + @Test + void returnsFalseWhenSourceSetNameIsNotMain() { + Mockito.when(subject.getName()).thenReturn("something-else"); + assertThat(SourceSetUtils.isMain(subject), is(false)); + } +} From f9628002cb4178c60859ebd02bf60baf0dbbf5cd Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:20:07 -0400 Subject: [PATCH 04/19] Introduce helper method for compileOnlyApi configuration Signed-off-by: Daniel Lacasse --- .../internal/util/GradleUtils.java | 13 +++++ .../internal/util/SourceSetUtils.java | 10 ++++ .../internal/util/GradleTestUtils.java | 11 ++++ ..._CompileOnlyApiConfigurationNameTests.java | 51 +++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradleUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/GradleTestUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_CompileOnlyApiConfigurationNameTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradleUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradleUtils.java new file mode 100644 index 00000000..73f50ca9 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradleUtils.java @@ -0,0 +1,13 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.util.GradleVersion; + +public final class GradleUtils { + /* visible for testing */ static GradleVersion CURRENT_GRADLE_VERSION = GradleVersion.current(); + + private GradleUtils() {} + + public static GradleVersion currentGradleVersion() { + return CURRENT_GRADLE_VERSION; + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java index 0c54e4f8..80de7ea5 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/SourceSetUtils.java @@ -5,6 +5,9 @@ import org.gradle.api.provider.Provider; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.util.GradleVersion; + +import static dev.gradleplugins.internal.util.GradleUtils.currentGradleVersion; /** * Additional helper methods for {@link SourceSet}. @@ -16,6 +19,13 @@ public static boolean isMain(SourceSet self) { return self.getName().equals("main"); } + public static String compileOnlyApiConfigurationName(SourceSet self) { + if (currentGradleVersion().compareTo(GradleVersion.version("6.7")) >= 0) { + return self.getCompileOnlyConfigurationName() + "Api"; + } + return self.getCompileOnlyConfigurationName(); + } + public static void sourceSets(Project project, Action action) { project.getExtensions().configure("sourceSets", action); } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/GradleTestUtils.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/GradleTestUtils.java new file mode 100644 index 00000000..f01b09f5 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/GradleTestUtils.java @@ -0,0 +1,11 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.util.GradleVersion; + +public final class GradleTestUtils { + private GradleTestUtils() {} + + public static void setCurrentGradleVersion(GradleVersion version) { + GradleUtils.CURRENT_GRADLE_VERSION = version; + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_CompileOnlyApiConfigurationNameTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_CompileOnlyApiConfigurationNameTests.java new file mode 100644 index 00000000..61fe4500 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/SourceSetUtils_CompileOnlyApiConfigurationNameTests.java @@ -0,0 +1,51 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.tasks.SourceSet; +import org.gradle.util.GradleVersion; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +@ExtendWith(MockitoExtension.class) +class SourceSetUtils_CompileOnlyApiConfigurationNameTests { + private static final GradleVersion BELOW_6_7 = GradleVersion.version("6.5"); + private static final GradleVersion ABOVE_6_7 = GradleVersion.version("6.9"); + @Mock SourceSet subject; + + @ParameterizedTest + @ValueSource(strings = {"6.7", "6.7.1", "6.9", "7.0"}) + void returnsCompileOnlyApiConfigurationNameOnGradleVersionAbove6_7(String version) { + GradleTestUtils.setCurrentGradleVersion(GradleVersion.version(version)); + Mockito.when(subject.getCompileOnlyConfigurationName()).thenReturn("compileOnly"); + assertThat(SourceSetUtils.compileOnlyApiConfigurationName(subject), equalTo("compileOnlyApi")); + } + + @ParameterizedTest + @ValueSource(strings = {"6.6.1", "6.5", "6.2.1"}) + void returnsCompileOnlyConfigurationNameOnGradleVersionBelow6_7(String version) { + GradleTestUtils.setCurrentGradleVersion(GradleVersion.version(version)); + Mockito.when(subject.getCompileOnlyConfigurationName()).thenReturn("compileOnly"); + assertThat(SourceSetUtils.compileOnlyApiConfigurationName(subject), equalTo("compileOnly")); + } + + @Test + void includesSourceSetNameInCompileOnlyConfigurationNameForNonMainSourceSet() { + GradleTestUtils.setCurrentGradleVersion(BELOW_6_7); + Mockito.when(subject.getCompileOnlyConfigurationName()).thenReturn("fooCompileOnly"); + assertThat(SourceSetUtils.compileOnlyApiConfigurationName(subject), equalTo("fooCompileOnly")); + } + + @Test + void includesSourceSetNameInCompileOnlyApiConfigurationNameForNonMainSourceSet() { + GradleTestUtils.setCurrentGradleVersion(ABOVE_6_7); + Mockito.when(subject.getCompileOnlyConfigurationName()).thenReturn("fooCompileOnly"); + assertThat(SourceSetUtils.compileOnlyApiConfigurationName(subject), equalTo("fooCompileOnlyApi")); + } +} From 82866972b2e1338ef1146083ad7ed8fa10f262f2 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:21:08 -0400 Subject: [PATCH 05/19] Introduce Provider utilities Signed-off-by: Daniel Lacasse --- .../internal/util/ProviderUtils.java | 35 +++++++++++++++++ .../ProviderUtils_DisallowChangesTests.java | 27 +++++++++++++ ...roviderUtils_FinalizeValueOnReadTests.java | 27 +++++++++++++ .../ProviderUtils_FinalizeValueTests.java | 27 +++++++++++++ .../util/ProviderUtils_IfPresentTests.java | 38 +++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_DisallowChangesTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueOnReadTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_IfPresentTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java new file mode 100644 index 00000000..a74c424d --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java @@ -0,0 +1,35 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.HasConfigurableValue; +import org.gradle.api.provider.Provider; + +import java.util.function.Consumer; + +public final class ProviderUtils { + private ProviderUtils() {} + + @SuppressWarnings("UnstableApiUsage") + public static S disallowChanges(S self) { + self.disallowChanges(); + return self; + } + + @SuppressWarnings("UnstableApiUsage") + public static S finalizeValue(S self) { + self.finalizeValue(); + return self; + } + + @SuppressWarnings("UnstableApiUsage") + public static S finalizeValueOnRead(S self) { + self.finalizeValueOnRead(); + return self; + } + + public static void ifPresent(Provider self, Consumer action) { + final S value = self.getOrNull(); + if (value != null) { + action.accept(value); + } + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_DisallowChangesTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_DisallowChangesTests.java new file mode 100644 index 00000000..ff5625e0 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_DisallowChangesTests.java @@ -0,0 +1,27 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.HasConfigurableValue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertSame; + +@SuppressWarnings("UnstableApiUsage") +@ExtendWith(MockitoExtension.class) +class ProviderUtils_DisallowChangesTests { + @Mock HasConfigurableValue value; + + @Test + void callsDisallowChanges() { + ProviderUtils.disallowChanges(value); + Mockito.verify(value).disallowChanges(); + } + + @Test + void returnsSameValue() { + assertSame(value, ProviderUtils.disallowChanges(value)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueOnReadTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueOnReadTests.java new file mode 100644 index 00000000..c39fa3e9 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueOnReadTests.java @@ -0,0 +1,27 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.HasConfigurableValue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertSame; + +@SuppressWarnings("UnstableApiUsage") +@ExtendWith(MockitoExtension.class) +class ProviderUtils_FinalizeValueOnReadTests { + @Mock HasConfigurableValue value; + + @Test + void callsFinalizeValue() { + ProviderUtils.finalizeValueOnRead(value); + Mockito.verify(value).finalizeValueOnRead(); + } + + @Test + void returnsSameValue() { + assertSame(value, ProviderUtils.finalizeValueOnRead(value)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueTests.java new file mode 100644 index 00000000..f0755dfa --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_FinalizeValueTests.java @@ -0,0 +1,27 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.HasConfigurableValue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertSame; + +@SuppressWarnings("UnstableApiUsage") +@ExtendWith(MockitoExtension.class) +class ProviderUtils_FinalizeValueTests { + @Mock HasConfigurableValue value; + + @Test + void callsFinalizeValue() { + ProviderUtils.finalizeValue(value); + Mockito.verify(value).finalizeValue(); + } + + @Test + void returnsSameValue() { + assertSame(value, ProviderUtils.finalizeValue(value)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_IfPresentTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_IfPresentTests.java new file mode 100644 index 00000000..9eb70bf4 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_IfPresentTests.java @@ -0,0 +1,38 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.Provider; +import org.gradle.api.provider.ProviderFactory; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.function.Consumer; + +import static dev.gradleplugins.internal.util.ProviderUtils.ifPresent; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; + +@ExtendWith(MockitoExtension.class) +class ProviderUtils_IfPresentTests { + @Mock Consumer presentAction; + + @Test + void callsActionIfProviderValueIsPresent() { + final Object value = new Object(); + ifPresent(providerFactory().provider(() -> value), presentAction); + Mockito.verify(presentAction).accept(value); + } + + @Test + void doesNoCallActionIfProviderValueIsAbsent() { + ifPresent(providerFactory().provider(() -> null), presentAction); + Mockito.verify(presentAction, never()).accept(any()); + } + + public static ProviderFactory providerFactory() { + return ProjectBuilder.builder().build().getProviders(); + } +} From b892f508918a2e9b0c06d4484a53070e8782c36a Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:21:56 -0400 Subject: [PATCH 06/19] Introduce lazy matching equivalent for domain object collection Signed-off-by: Daniel Lacasse --- .../util/DomainObjectCollectionUtils.java | 16 +++++++ ...inObjectCollectionUtils_MatchingTests.java | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_MatchingTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java new file mode 100644 index 00000000..93548aca --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java @@ -0,0 +1,16 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; +import org.gradle.api.specs.Spec; + +public final class DomainObjectCollectionUtils { + private DomainObjectCollectionUtils() {} + + public static Action matching(Spec spec, Action action) { + return it -> { + if (spec.isSatisfiedBy(it)) { + action.execute(it); + } + }; + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_MatchingTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_MatchingTests.java new file mode 100644 index 00000000..ba21f34a --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_MatchingTests.java @@ -0,0 +1,42 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; +import org.gradle.api.specs.Spec; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.matching; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; + +@ExtendWith(MockitoExtension.class) +class DomainObjectCollectionUtils_MatchingTests { + @Mock Spec spec; + @Mock Action delegate; + Action subject; + + @BeforeEach + void createSubject() { + subject = matching(spec, delegate); + } + + @Test + void callsDelegateActionWhenSpecIsSatisfied() { + final Object value = new Object(); + Mockito.when(spec.isSatisfiedBy(value)).thenReturn(true); + subject.execute(value); + Mockito.verify(delegate).execute(value); + } + + @Test + void doesNotCallsDelegateActionWhenSpecIsNotSatisfied() { + final Object value = new Object(); + Mockito.when(spec.isSatisfiedBy(value)).thenReturn(false); + subject.execute(value); + Mockito.verify(delegate, never()).execute(value); + } +} From 86cd68357e2a6a0dc7cd6752f4b2f5502e4764ed Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:22:46 -0400 Subject: [PATCH 07/19] Introduce utility method to ignore action parameter Signed-off-by: Daniel Lacasse --- .../internal/util/ActionUtils.java | 11 ++++++++ .../ActionUtils_WithoutParameterTests.java | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ActionUtils.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ActionUtils_WithoutParameterTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ActionUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ActionUtils.java new file mode 100644 index 00000000..2c9bcc9a --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ActionUtils.java @@ -0,0 +1,11 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; + +public final class ActionUtils { + private ActionUtils() {} + + public static Action withoutParameter(Runnable runnable) { + return __ -> runnable.run(); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ActionUtils_WithoutParameterTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ActionUtils_WithoutParameterTests.java new file mode 100644 index 00000000..0196c46e --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ActionUtils_WithoutParameterTests.java @@ -0,0 +1,28 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Action; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static dev.gradleplugins.internal.util.ActionUtils.withoutParameter; + +@ExtendWith(MockitoExtension.class) +class ActionUtils_WithoutParameterTests { + @Mock Runnable runnable; + Action subject; + + @BeforeEach + void createSubject() { + subject = withoutParameter(runnable); + } + + @Test + void callsRunnableOnActionExecution() { + subject.execute(new Object()); + Mockito.verify(runnable).run(); + } +} From 7d21e3a87c35feeeb11b5528086659e5096aabe0 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:27:44 -0400 Subject: [PATCH 08/19] Remove Provider-specific in coordinate matcher Signed-off-by: Daniel Lacasse --- .../GradlePluginDevelopmentTestSuiteDependencies.java | 3 ++- .../internal/GradlePluginDevelopmentTestSuiteInternal.java | 4 ++-- ...velopmentTestSuiteMinimumGradleVersionIntegrationTest.java | 4 ++-- .../src/test/groovy/dev/gradleplugins/ProjectMatchers.java | 3 --- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/GradlePluginDevelopmentTestSuiteDependencies.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/GradlePluginDevelopmentTestSuiteDependencies.java index 43c1c140..45fa47de 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/GradlePluginDevelopmentTestSuiteDependencies.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/GradlePluginDevelopmentTestSuiteDependencies.java @@ -4,6 +4,7 @@ import org.gradle.api.NamedDomainObjectProvider; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ModuleDependency; +import org.gradle.api.provider.Provider; public interface GradlePluginDevelopmentTestSuiteDependencies { void implementation(Object notation); @@ -38,7 +39,7 @@ public interface GradlePluginDevelopmentTestSuiteDependencies { Object gradleTestKit(String version); @Deprecated - Object groovy(); + Provider groovy(); @Deprecated Object groovy(String version); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentTestSuiteInternal.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentTestSuiteInternal.java index 41a58862..494b09d1 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentTestSuiteInternal.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentTestSuiteInternal.java @@ -271,8 +271,8 @@ public Object gradleTestKit(String version) { } @Override - public Object groovy() { - return defaultGroovyVersion.map(GradlePluginDevelopmentDependencyExtensionInternal.of(getDependencies())::groovy); + public Provider groovy() { + return defaultGroovyVersion.map(this::groovy); } @Override diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java index 267b920d..f95f271c 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java @@ -35,7 +35,7 @@ void throwsExceptionOnCoverageForMinimumVersionQuery() { @Test void returnsGroovyDependencyForCurrentGradleVersion() { - assertThat(subject.getDependencies().groovy(), coordinate("org.codehaus.groovy:groovy-all:2.5.8")); + assertThat(subject.getDependencies().groovy(), providerOf(coordinate("org.codehaus.groovy:groovy-all:2.5.8"))); } @Nested @@ -75,7 +75,7 @@ void returnsDevelCompatibilityMinimumGradleVersion() { @Test void returnsGroovyDependencyForMinimumGradleVersion() { - assertThat(subject.getDependencies().groovy(), coordinate("org.codehaus.groovy:groovy-all:2.4.12")); + assertThat(subject.getDependencies().groovy(), providerOf(coordinate("org.codehaus.groovy:groovy-all:2.4.12"))); } } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java index bcda1152..1b9825e7 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java @@ -130,9 +130,6 @@ public static Matcher coordinate(String coordinate) { @Override protected String featureValueOf(Object actual) { Dependency dependency = null; - if (actual instanceof Provider) { - actual = ((Provider) actual).get(); - } if (actual instanceof Dependency) { final StringBuilder builder = new StringBuilder(); builder.append(((Dependency) actual).getGroup()); From 2a31f0d2a5723a5e8a0bd66b726a5d79eb797d2d Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:32:07 -0400 Subject: [PATCH 09/19] Defer testing strategy version resolution Signed-off-by: Daniel Lacasse --- ...ateTestTasksFromTestingStrategiesRule.java | 34 +++++++++++++++++-- ...mpositeTestingStrategyIntegrationTest.java | 8 +++-- ...elopmentFunctionalTestingPluginTest.groovy | 4 ++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/CreateTestTasksFromTestingStrategiesRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/CreateTestTasksFromTestingStrategiesRule.java index 30ea73d2..7a135120 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/CreateTestTasksFromTestingStrategiesRule.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/CreateTestTasksFromTestingStrategiesRule.java @@ -14,6 +14,8 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.util.GUtil; +import java.io.IOException; +import java.io.Serializable; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Stream; @@ -69,15 +71,41 @@ private Action configureTestingStrategy(GradlePluginDevelopmentTestSuite t Stream.of(strategy) .flatMap(this::unpackCompositeTestingStrategy) .flatMap(this::onlyCoverageTestingStrategy) - .map(GradleVersionCoverageTestingStrategy::getVersion) .findFirst() .ifPresent(setDefaultGradleVersionSystemProperty(task)); testingStrategyProperty(task).set(strategy); }; } - private static Consumer setDefaultGradleVersionSystemProperty(Test task) { - return version -> task.systemProperty("dev.gradleplugins.defaultGradleVersion", version); + private static Consumer setDefaultGradleVersionSystemProperty(Test task) { + return version -> task.systemProperty("dev.gradleplugins.defaultGradleVersion", new DefaultGradleVersionUnderTest(version)); + } + + private static class DefaultGradleVersionUnderTest implements Serializable { + private final GradleVersionCoverageTestingStrategy strategy; + private String value; + + private DefaultGradleVersionUnderTest(GradleVersionCoverageTestingStrategy strategy) { + this.strategy = strategy; + } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + if (value == null) { + value = strategy.getVersion(); + } + out.writeUTF(value); + } + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + value = in.readUTF(); + } + + @Override + public String toString() { + if (value == null) { + value = strategy.getVersion(); + } + return value; + } } private Stream onlyCoverageTestingStrategy(GradlePluginTestingStrategy strategy) { diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCompositeTestingStrategyIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCompositeTestingStrategyIntegrationTest.java index c11c2535..56bc4194 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCompositeTestingStrategyIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteCompositeTestingStrategyIntegrationTest.java @@ -17,7 +17,11 @@ import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.iterableWithSize; class GradlePluginDevelopmentTestSuiteCompositeTestingStrategyIntegrationTest { private final Project project = ProjectBuilder.builder().build(); @@ -45,7 +49,7 @@ void usesCompositeStrategyOnEachTestTasks() { @Test void detectsComposedCoverageVersionOnEachTestTasks() { - assertThat(subject.getTestTasks().getElements().map(transformEach(this::asSystemProperties)), providerOf(contains(hasEntry("dev.gradleplugins.defaultGradleVersion", "6.7"), hasEntry("dev.gradleplugins.defaultGradleVersion", "7.0")))); + assertThat(subject.getTestTasks().getElements().map(transformEach(this::asSystemProperties)), providerOf(contains(hasEntry(is("dev.gradleplugins.defaultGradleVersion"), hasToString("6.7")), hasEntry(is("dev.gradleplugins.defaultGradleVersion"), hasToString("7.0"))))); } private static Transformer, Iterable> transformEach(Function mapper) { diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentFunctionalTestingPluginTest.groovy b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentFunctionalTestingPluginTest.groovy index 4d169b07..68915fb0 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentFunctionalTestingPluginTest.groovy +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentFunctionalTestingPluginTest.groovy @@ -6,6 +6,8 @@ import org.gradle.testfixtures.ProjectBuilder import spock.lang.Specification import spock.lang.Unroll +import static java.util.Objects.toString + abstract class AbstractGradlePluginDevelopmentFunctionalTestingPluginTest extends Specification { def project = ProjectBuilder.builder().build() @@ -80,7 +82,7 @@ abstract class AbstractGradlePluginDevelopmentFunctionalTestingPluginTest extend project.evaluate() then: - project.tasks.functionalTest.systemProperties['dev.gradleplugins.defaultGradleVersion'] == expectedVersion + toString(project.tasks.functionalTest.systemProperties['dev.gradleplugins.defaultGradleVersion'], null) == expectedVersion where: coverage | expectedVersion From 12b380e98ee32ba420bae79837ebfe3d36399852 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:34:43 -0400 Subject: [PATCH 10/19] Avoid resolving Gradle version during equals/hashCode Signed-off-by: Daniel Lacasse --- ...ePluginTestingStrategyFactoryInternal.java | 40 ++++++++++++++++--- ...sionCoverageTestingStrategyEqualsTest.java | 8 ++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginTestingStrategyFactoryInternal.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginTestingStrategyFactoryInternal.java index fe32a87d..f94b80bb 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginTestingStrategyFactoryInternal.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginTestingStrategyFactoryInternal.java @@ -35,7 +35,7 @@ public GradlePluginTestingStrategyFactoryInternal(Provider minimumVersio @Override public GradleVersionCoverageTestingStrategy getCoverageForMinimumVersion() { - return new DefaultGradleVersionCoverageTestingStrategy(MINIMUM_GRADLE, () -> minimumVersion.get(), () -> { + return new DefaultGradleVersionCoverageTestingStrategy(MINIMUM_GRADLE, new MinimumVersionSupplier(minimumVersion), () -> { val result = minimumVersion.get(); assertKnownMinimumVersion(result); return result; @@ -44,7 +44,7 @@ public GradleVersionCoverageTestingStrategy getCoverageForMinimumVersion() { @Override public GradleVersionCoverageTestingStrategy getCoverageForLatestNightlyVersion() { - return new DefaultGradleVersionCoverageTestingStrategy(LATEST_NIGHTLY, () -> "latest-nightly", () -> releasedVersions.getMostRecentSnapshot().getVersion()); + return new DefaultGradleVersionCoverageTestingStrategy(LATEST_NIGHTLY, new FixedVersionSupplier("latest-nightly"), () -> releasedVersions.getMostRecentSnapshot().getVersion()); } @Override @@ -72,12 +72,12 @@ private static String format(VersionNumber version) { @Override public GradleVersionCoverageTestingStrategy getCoverageForLatestGlobalAvailableVersion() { - return new DefaultGradleVersionCoverageTestingStrategy(LATEST_GLOBAL_AVAILABLE, () -> "latest-released", () -> releasedVersions.getMostRecentRelease().getVersion()); + return new DefaultGradleVersionCoverageTestingStrategy(LATEST_GLOBAL_AVAILABLE, new FixedVersionSupplier("latest-released"), () -> releasedVersions.getMostRecentRelease().getVersion()); } @Override public GradleVersionCoverageTestingStrategy coverageForGradleVersion(String version) { - return new DefaultGradleVersionCoverageTestingStrategy(version, () -> version, () -> { + return new DefaultGradleVersionCoverageTestingStrategy(version, new FixedVersionSupplier(version), () -> { if (!isKnownVersion(version)) { throw new IllegalArgumentException(String.format("Unknown Gradle version '%s' for adhoc testing strategy.", version)); } @@ -132,6 +132,34 @@ private void assertKnownMinimumVersion(String version) { } } + @EqualsAndHashCode + private static final class MinimumVersionSupplier implements Supplier { + @EqualsAndHashCode.Exclude private final Provider value; + + private MinimumVersionSupplier(Provider value) { + this.value = value; + } + + @Override + public String get() { + return value.get(); + } + } + + @EqualsAndHashCode + private static final class FixedVersionSupplier implements Supplier { + private final String value; + + private FixedVersionSupplier(String value) { + this.value = value; + } + + @Override + public String get() { + return value; + } + } + private final class DefaultGradleVersionCoverageTestingStrategy implements GradlePluginTestingStrategyInternal, GradleVersionCoverageTestingStrategy { private final String name; private final Supplier rawVersionSupplier; @@ -171,12 +199,12 @@ public boolean equals(Object o) { return false; } DefaultGradleVersionCoverageTestingStrategy that = (DefaultGradleVersionCoverageTestingStrategy) o; - return Objects.equals(rawVersionSupplier.get(), that.rawVersionSupplier.get()); + return Objects.equals(rawVersionSupplier, that.rawVersionSupplier); } @Override public int hashCode() { - return Objects.hash(rawVersionSupplier.get(), getName()); + return Objects.hash(rawVersionSupplier, getName()); } @Override diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradleVersionCoverageTestingStrategyEqualsTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradleVersionCoverageTestingStrategyEqualsTest.java index af57c8f2..3c1c99ab 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradleVersionCoverageTestingStrategyEqualsTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradleVersionCoverageTestingStrategyEqualsTest.java @@ -6,7 +6,9 @@ import org.gradle.testfixtures.ProjectBuilder; import org.junit.jupiter.api.Test; -import static dev.gradleplugins.GradleReleases.*; +import static dev.gradleplugins.GradleReleases.current; +import static dev.gradleplugins.GradleReleases.globalAvailable; +import static dev.gradleplugins.GradleReleases.snapshotFor; import static dev.gradleplugins.GradleVersionsTestService.builder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -29,8 +31,8 @@ void minimumVersionsAreEquals() { } @Test - void minimumVersionIsEqualToExactGradleVersion() { - assertEquals(factory.coverageForGradleVersion("7.1"), factory.getCoverageForMinimumVersion()); + void minimumVersionIsNotEqualToExactGradleVersion() { + assertNotEquals(factory.coverageForGradleVersion("7.1"), factory.getCoverageForMinimumVersion()); } @Test From 750f75a337081c836982ab3310049e6c3dd101be Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:35:27 -0400 Subject: [PATCH 11/19] Introduce more matchers for dependencies Signed-off-by: Daniel Lacasse --- .../dev/gradleplugins/ProjectMatchers.java | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java index 1b9825e7..168b0dde 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/ProjectMatchers.java @@ -4,8 +4,11 @@ import org.gradle.api.NamedDomainObjectCollectionSchema; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ConfigurationPublications; import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.repositories.ArtifactRepository; +import org.gradle.api.capabilities.Capability; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.ExtensionsSchema; import org.gradle.api.plugins.PluginAware; @@ -22,7 +25,7 @@ public final class ProjectMatchers { public static Matcher extensions(Matcher> matcher) { - return new FeatureMatcher>(matcher, "", "") { + return new FeatureMatcher>(matcher, "a extension aware object", "extension aware object") { @Override protected Iterable featureValueOf(T actual) { return ((ExtensionAware) actual).getExtensions().getExtensionsSchema().getElements(); @@ -125,10 +128,10 @@ public void describeTo(Description description) { }; } - public static Matcher coordinate(String coordinate) { - return new FeatureMatcher(equalTo(coordinate), "", "") { + public static Matcher coordinate(String coordinate) { + return new FeatureMatcher(equalTo(coordinate), "", "") { @Override - protected String featureValueOf(Object actual) { + protected String featureValueOf(T actual) { Dependency dependency = null; if (actual instanceof Dependency) { final StringBuilder builder = new StringBuilder(); @@ -136,6 +139,28 @@ protected String featureValueOf(Object actual) { builder.append(":").append(((Dependency) actual).getName()); builder.append(":").append(((Dependency) actual).getVersion()); return builder.toString(); + } else if (actual instanceof Capability) { + final StringBuilder builder = new StringBuilder(); + builder.append(((Capability) actual).getGroup()); + builder.append(":").append(((Capability) actual).getName()); + builder.append(":").append(((Capability) actual).getVersion()); + return builder.toString(); + } + throw new UnsupportedOperationException(); + } + }; + } + + public static Matcher capabilities(Matcher> matcher) { + return new FeatureMatcher>(matcher, "", "") { + @Override + protected Iterable featureValueOf(T actual) { + if (actual instanceof Dependency) { + return ((ModuleDependency) actual).getRequestedCapabilities(); + } else if (actual instanceof ConfigurationPublications) { + @SuppressWarnings("unchecked") + final Iterable result = (Iterable) ((ConfigurationPublications) actual).getCapabilities(); + return result; } throw new UnsupportedOperationException(); } From 03a99f8081cfb60d17bc48df91f2f926c762e66f Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:38:59 -0400 Subject: [PATCH 12/19] Remove JVM compability properties Signed-off-by: Daniel Lacasse --- ...izableJvmCompatibilityPropertyAdapter.java | 40 ---------- .../jvm/JvmCompatibilityProperties.java | 23 ------ .../jvm/JvmCompatibilityProperty.java | 9 --- .../jvm/JvmCompatibilityPropertyFactory.java | 48 ------------ .../jvm/JvmSourceCompatibilityProperty.java | 36 --------- .../jvm/JvmTargetCompatibilityProperty.java | 36 --------- ...nsionFinalizeComponentIntegrationTest.java | 61 --------------- ...leJvmCompatibilityPropertyAdapterTest.java | 55 -------------- ...eCompatibilityPropertyIntegrationTest.java | 74 ------------------- .../JvmSourceCompatibilityPropertyTest.java | 54 -------------- ...tCompatibilityPropertyIntegrationTest.java | 74 ------------------- .../JvmTargetCompatibilityPropertyTest.java | 53 ------------- .../jvm/MockJvmCompatibilityProperty.java | 26 ------- 13 files changed, 589 deletions(-) delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapter.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperties.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperty.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityPropertyFactory.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityProperty.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityProperty.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentCompatibilityExtensionFinalizeComponentIntegrationTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapterTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyIntegrationTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyIntegrationTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyTest.java delete mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/MockJvmCompatibilityProperty.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapter.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapter.java deleted file mode 100644 index 0df7c612..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapter.java +++ /dev/null @@ -1,40 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -import java.util.Objects; - -public final class FinalizableJvmCompatibilityPropertyAdapter implements JvmCompatibilityProperty { - private final JvmCompatibilityProperty delegate; - private final JavaVersion initialValue; - - public FinalizableJvmCompatibilityPropertyAdapter(JvmCompatibilityProperty delegate) { - this.delegate = delegate; - this.initialValue = delegate.get(); - - // The plugins assume no one will ever use this value - delegate.set(JavaVersion.VERSION_1_1); - } - - @Override - public JavaVersion get() { - return delegate.get(); - } - - @Override - public void set(JavaVersion value) { - Objects.requireNonNull(value); - // Only set the value if we still have the magical default - if (delegate.get().equals(JavaVersion.VERSION_1_1)) { - delegate.set(value); - } - } - - @Override - public void finalizeValue() { - // Restore default values if needed - if (delegate.get().equals(JavaVersion.VERSION_1_1)) { - delegate.set(initialValue); - } - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperties.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperties.java deleted file mode 100644 index 0a4e2159..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperties.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -public final class JvmCompatibilityProperties { - private final JvmTargetCompatibilityProperty targetCompatibility; - private final JvmSourceCompatibilityProperty sourceCompatibility; - - public JvmCompatibilityProperties(JvmTargetCompatibilityProperty targetCompatibility, JvmSourceCompatibilityProperty sourceCompatibility) { - this.targetCompatibility = targetCompatibility; - this.sourceCompatibility = sourceCompatibility; - } - - public void set(JavaVersion value) { - targetCompatibility.set(value); - sourceCompatibility.set(value); - } - - public void finalizeValues() { - targetCompatibility.finalizeValue(); - sourceCompatibility.finalizeValue(); - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperty.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperty.java deleted file mode 100644 index e491b12e..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityProperty.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -public interface JvmCompatibilityProperty { - JavaVersion get(); - void set(JavaVersion value); - void finalizeValue(); -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityPropertyFactory.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityPropertyFactory.java deleted file mode 100644 index f937882e..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmCompatibilityPropertyFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; -import org.gradle.api.plugins.JavaPluginExtension; - -public class JvmCompatibilityPropertyFactory { - public static JvmCompatibilityProperties of(JavaPluginExtension java) { - return new JvmCompatibilityProperties(ofTargetCompatibility(java), ofSourceCompatibility(java)); - } - - public static JvmSourceCompatibilityProperty ofSourceCompatibility(JavaPluginExtension java) { - return new JvmSourceCompatibilityProperty(new FinalizableJvmCompatibilityPropertyAdapter(new JvmCompatibilityProperty() { - @Override - public JavaVersion get() { - return java.getSourceCompatibility(); - } - - @Override - public void set(JavaVersion value) { - java.setSourceCompatibility(value); - } - - @Override - public void finalizeValue() { - // do nothing - } - })); - } - - public static JvmTargetCompatibilityProperty ofTargetCompatibility(JavaPluginExtension java) { - return new JvmTargetCompatibilityProperty(new FinalizableJvmCompatibilityPropertyAdapter(new JvmCompatibilityProperty() { - @Override - public JavaVersion get() { - return java.getTargetCompatibility(); - } - - @Override - public void set(JavaVersion value) { - java.setTargetCompatibility(value); - } - - @Override - public void finalizeValue() { - // do nothing - } - })); - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityProperty.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityProperty.java deleted file mode 100644 index de272203..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityProperty.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -import java.util.Objects; - -public final class JvmSourceCompatibilityProperty implements JvmCompatibilityProperty { - private final JvmCompatibilityProperty delegate; - private boolean finalized = false; - - public JvmSourceCompatibilityProperty(JvmCompatibilityProperty delegate) { - this.delegate = delegate; - } - - @Override - public JavaVersion get() { - return delegate.get(); - } - - @Override - public void set(JavaVersion value) { - Objects.requireNonNull(value); - if (finalized) { - throw new IllegalStateException("The value for property 'sourceCompatibility' is final and cannot be changed any further."); - } - delegate.set(value); - } - - @Override - public void finalizeValue() { - if (!finalized) { - delegate.finalizeValue(); - finalized = true; - } - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityProperty.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityProperty.java deleted file mode 100644 index 0c223666..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityProperty.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -import java.util.Objects; - -public final class JvmTargetCompatibilityProperty implements JvmCompatibilityProperty { - private final JvmCompatibilityProperty delegate; - private boolean finalized = false; - - public JvmTargetCompatibilityProperty(JvmCompatibilityProperty delegate) { - this.delegate = delegate; - } - - @Override - public JavaVersion get() { - return delegate.get(); - } - - @Override - public void set(JavaVersion value) { - Objects.requireNonNull(value); - if (finalized) { - throw new IllegalStateException("The value for property 'targetCompatibility' is final and cannot be changed any further."); - } - delegate.set(value); - } - - @Override - public void finalizeValue() { - if (!finalized) { - delegate.finalizeValue(); - finalized = true; - } - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentCompatibilityExtensionFinalizeComponentIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentCompatibilityExtensionFinalizeComponentIntegrationTest.java deleted file mode 100644 index b131886d..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentCompatibilityExtensionFinalizeComponentIntegrationTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package dev.gradleplugins; - -import dev.gradleplugins.internal.FinalizableComponent; -import org.gradle.api.Project; -import org.gradle.testfixtures.ProjectBuilder; -import org.gradle.util.GradleVersion; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; -import static dev.gradleplugins.ProjectMatchers.providerOf; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; -import static org.gradle.api.JavaVersion.VERSION_11; -import static org.gradle.api.JavaVersion.VERSION_12; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.*; - -class GradlePluginDevelopmentCompatibilityExtensionFinalizeComponentIntegrationTest { - private final Project project = ProjectBuilder.builder().build(); - private GradlePluginDevelopmentCompatibilityExtension subject; - - @BeforeEach - void setup() { - project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-base"); - project.getPluginManager().apply("java-gradle-plugin"); - subject = compatibility(gradlePlugin(project)); - ((FinalizableComponent) subject).finalizeComponent(); - } - - @Test - void canFinalizeTestSuiteMultipleTime() { - assertDoesNotThrow(((FinalizableComponent) subject)::finalizeComponent); - } - - @Test - void defaultsMinimumGradleVersionToCurrentGradleVersion() { - assertThat(subject.getMinimumGradleVersion(), providerOf(GradleVersion.current().getVersion())); - } - - @Test - void disallowChangesToMinimumGradleVersion() { - final Throwable ex = assertThrows(RuntimeException.class, () -> subject.getMinimumGradleVersion().set("6.9")); - assertEquals("The value for property 'minimumGradleVersion' cannot be changed any further.", ex.getMessage()); - } - - @Test - void disallowChangesToGradleApiVersion() { - final Throwable ex = assertThrows(RuntimeException.class, () -> subject.getGradleApiVersion().set("6.9")); - assertEquals("The value for property 'gradleApiVersion' cannot be changed any further.", ex.getMessage()); - } - - @Test - void doesNotChangesJvmCompatibilitiesOnAdditionalFinalize() { - java(project).setSourceCompatibility(VERSION_11); - java(project).setTargetCompatibility(VERSION_12); - ((FinalizableComponent) subject).finalizeComponent(); - assertEquals(VERSION_11, java(project).getSourceCompatibility()); - assertEquals(VERSION_12, java(project).getTargetCompatibility()); - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapterTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapterTest.java deleted file mode 100644 index 4ebbfec0..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/FinalizableJvmCompatibilityPropertyAdapterTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.junit.jupiter.api.Test; - -import static org.gradle.api.JavaVersion.*; -import static org.junit.jupiter.api.Assertions.*; - -class FinalizableJvmCompatibilityPropertyAdapterTest { - private final MockJvmCompatibilityProperty delegate = new MockJvmCompatibilityProperty(VERSION_1_8); - private final FinalizableJvmCompatibilityPropertyAdapter subject = new FinalizableJvmCompatibilityPropertyAdapter(delegate); - - @Test - void setsDelegateToJavaVersion1_1() { - assertEquals(VERSION_1_1, delegate.value); - } - - @Test - void throwsNullPointerExceptionWhenSetValueIsNull() { - assertThrows(NullPointerException.class, () -> subject.set(null)); - } - - @Test - void forwardsGetToDelegate() { - delegate.set(VERSION_1_7); - assertSame(VERSION_1_7, subject.get()); - } - - @Test - void forwardsSetToDelegateOnlyWhenValueIsJavaVersion1_1() { - delegate.value = VERSION_1_1; - subject.set(VERSION_1_5); - assertEquals(VERSION_1_5, delegate.value); - } - - @Test - void doesNotForwardSetToDelegateWhenValueIsNotJavaVersion1_1() { - delegate.value = VERSION_1_4; - subject.set(VERSION_1_9); - assertEquals(VERSION_1_4, delegate.value); - } - - @Test - void restoresInitialValueToDelegateWhenValueIsJavaVersion1_1OnFinalizeValue() { - delegate.value = VERSION_1_1; - subject.finalizeValue(); - assertEquals(VERSION_1_8, delegate.value); - } - - @Test - void doesNotRestoresInitialValueToDelegateWhenValueIsJavaVersion1_1OnFinalizeValue() { - delegate.value = VERSION_11; - subject.finalizeValue(); - assertEquals(VERSION_11, delegate.value); - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyIntegrationTest.java deleted file mode 100644 index 42afc906..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyIntegrationTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; -import org.gradle.api.Project; -import org.gradle.testfixtures.ProjectBuilder; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; -import static org.gradle.api.JavaVersion.*; -import static org.junit.jupiter.api.Assertions.*; - -class JvmSourceCompatibilityPropertyIntegrationTest { - private static final JavaVersion INITIAL_VALUE = VERSION_1_8; - private final Project project = ProjectBuilder.builder().build(); - private JvmSourceCompatibilityProperty subject; - - @BeforeEach - void setup() { - project.getPluginManager().apply("java-base"); - java(project).setSourceCompatibility(INITIAL_VALUE); - assertNotEquals(VERSION_1_1, INITIAL_VALUE); - subject = JvmCompatibilityPropertyFactory.ofSourceCompatibility(java(project)); - } - - @Test - void throwsNullPointerExceptionWhenSetValueIsNull() { - assertThrows(NullPointerException.class, () -> subject.set(null)); - } - - @Test - void initializesToJavaVersion1_1() { - assertEquals(VERSION_1_1, java(project).getSourceCompatibility()); - } - - @Test - void restoresInitialValueOnFinalizeValue() { - subject.finalizeValue(); - assertEquals(INITIAL_VALUE, java(project).getSourceCompatibility()); - } - - @Test - void usesNewValueOnSet() { - subject.set(VERSION_1_9); - assertEquals(VERSION_1_9, java(project).getSourceCompatibility()); - } - - @Nested - class WhenExtensionValueChangedTest { - @BeforeEach - void changesExtensionValue() { - java(project).setSourceCompatibility(VERSION_11); - } - - @Test - void returnsCurrentExtensionValue() { - assertEquals(VERSION_11, subject.get()); - } - - @Test - void doesNotRestoreInitialValueOnFinalizeValue() { - subject.finalizeValue(); - assertNotEquals(INITIAL_VALUE, VERSION_11); - assertEquals(VERSION_11, java(project).getSourceCompatibility()); - } - - @Test - void ignoresNewValueOnSet() { - subject.set(VERSION_1_9); - assertEquals(VERSION_11, java(project).getSourceCompatibility()); - } - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyTest.java deleted file mode 100644 index e5d6831f..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmSourceCompatibilityPropertyTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import static org.gradle.api.JavaVersion.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -class JvmSourceCompatibilityPropertyTest { - private final JvmCompatibilityProperty delegate = Mockito.mock(JvmCompatibilityProperty.class); - private final JvmSourceCompatibilityProperty subject = new JvmSourceCompatibilityProperty(delegate); - - @Test - void throwsNullPointerExceptionWhenSetValueIsNull() { - assertThrows(NullPointerException.class, () -> subject.set(null)); - } - - @Test - void forwardsGetToDelegate() { - when(delegate.get()).thenReturn(VERSION_1_8); - - assertSame(VERSION_1_8, subject.get()); - verify(delegate).get(); - } - - @Test - void forwardsSetToDelegate() { - subject.set(VERSION_1_5); - verify(delegate).set(VERSION_1_5); - } - - @Test - void forwardsFinalizeValueToDelegate() { - subject.finalizeValue(); - verify(delegate).finalizeValue(); - } - - @Test - void disallowChangesWhenFinalized() { - subject.finalizeValue(); - final Throwable ex = assertThrows(IllegalStateException.class, () -> subject.set(VERSION_12)); - assertEquals("The value for property 'sourceCompatibility' is final and cannot be changed any further.", ex.getMessage()); - } - - @Test - void doesNotForwardsFinalizeValueToDelegateOnSubsequentFinalize() { - subject.finalizeValue(); - subject.finalizeValue(); - verify(delegate).finalizeValue(); - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyIntegrationTest.java deleted file mode 100644 index 0ea006c8..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyIntegrationTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; -import org.gradle.api.Project; -import org.gradle.testfixtures.ProjectBuilder; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; -import static org.gradle.api.JavaVersion.*; -import static org.junit.jupiter.api.Assertions.*; - -class JvmTargetCompatibilityPropertyIntegrationTest { - private static final JavaVersion INITIAL_VALUE = VERSION_1_8; - private final Project project = ProjectBuilder.builder().build(); - private JvmTargetCompatibilityProperty subject; - - @BeforeEach - void setup() { - project.getPluginManager().apply("java-base"); - java(project).setTargetCompatibility(INITIAL_VALUE); - assertNotEquals(VERSION_1_1, INITIAL_VALUE); - subject = JvmCompatibilityPropertyFactory.ofTargetCompatibility(java(project)); - } - - @Test - void throwsNullPointerExceptionWhenSetValueIsNull() { - assertThrows(NullPointerException.class, () -> subject.set(null)); - } - - @Test - void initializesToJavaVersion1_1() { - assertEquals(VERSION_1_1, java(project).getTargetCompatibility()); - } - - @Test - void restoresInitialValueOnFinalizeValue() { - subject.finalizeValue(); - assertEquals(INITIAL_VALUE, java(project).getTargetCompatibility()); - } - - @Test - void usesNewValueOnSet() { - subject.set(VERSION_1_9); - assertEquals(VERSION_1_9, java(project).getTargetCompatibility()); - } - - @Nested - class WhenExtensionValueChangedTest { - @BeforeEach - void changesExtensionValue() { - java(project).setTargetCompatibility(VERSION_11); - } - - @Test - void returnsCurrentExtensionValue() { - assertEquals(VERSION_11, subject.get()); - } - - @Test - void doesNotRestoreInitialValueOnFinalizeValue() { - subject.finalizeValue(); - assertNotEquals(INITIAL_VALUE, VERSION_11); - assertEquals(VERSION_11, java(project).getTargetCompatibility()); - } - - @Test - void ignoresNewValueOnSet() { - subject.set(VERSION_1_9); - assertEquals(VERSION_11, java(project).getTargetCompatibility()); - } - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyTest.java deleted file mode 100644 index fdac1c2f..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/JvmTargetCompatibilityPropertyTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import static org.gradle.api.JavaVersion.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class JvmTargetCompatibilityPropertyTest { - private final JvmCompatibilityProperty delegate = Mockito.mock(JvmCompatibilityProperty.class); - private final JvmTargetCompatibilityProperty subject = new JvmTargetCompatibilityProperty(delegate); - - @Test - void throwsNullPointerExceptionWhenSetValueIsNull() { - assertThrows(NullPointerException.class, () -> subject.set(null)); - } - - @Test - void forwardsGetToDelegate() { - when(delegate.get()).thenReturn(VERSION_1_9); - - assertSame(VERSION_1_9, subject.get()); - verify(delegate).get(); - } - - @Test - void forwardsSetToDelegate() { - subject.set(VERSION_1_6); - verify(delegate).set(VERSION_1_6); - } - - @Test - void forwardsFinalizeValueToDelegate() { - subject.finalizeValue(); - verify(delegate).finalizeValue(); - } - - @Test - void disallowChangesWhenFinalized() { - subject.finalizeValue(); - final Throwable ex = assertThrows(IllegalStateException.class, () -> subject.set(VERSION_11)); - assertEquals("The value for property 'targetCompatibility' is final and cannot be changed any further.", ex.getMessage()); - } - - @Test - void doesNotForwardsFinalizeValueToDelegateOnSubsequentFinalize() { - subject.finalizeValue(); - subject.finalizeValue(); - verify(delegate).finalizeValue(); - } -} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/MockJvmCompatibilityProperty.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/MockJvmCompatibilityProperty.java deleted file mode 100644 index 81accaae..00000000 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/jvm/MockJvmCompatibilityProperty.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.gradleplugins.internal.jvm; - -import org.gradle.api.JavaVersion; - -final class MockJvmCompatibilityProperty implements JvmCompatibilityProperty { - public JavaVersion value; - - public MockJvmCompatibilityProperty(JavaVersion defaultValue) { - this.value = defaultValue; - } - - @Override - public JavaVersion get() { - return value; - } - - @Override - public void set(JavaVersion value) { - this.value = value; - } - - @Override - public void finalizeValue() { - // do nothing - } -} From 74badb6ab69f1b3babeaa162d9b2f24c4d30216a Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 14:45:32 -0400 Subject: [PATCH 13/19] Convert base logic into individual rules Signed-off-by: Daniel Lacasse --- ...nDevelopmentExtensionFunctionalTest.groovy | 2 +- ...adlePluginDevelopmentTestSuiteFactory.java | 5 +- ...evelopmentDependencyExtensionInternal.java | 5 + ...dlePluginDevelopmentExtensionInternal.java | 8 +- .../dev/gradleplugins/internal/RuleGroup.java | 5 + ...pendencyToCompileOnlyApiConfiguration.java | 32 ------ ...uginDevelopmentCompatibilityExtension.java | 63 ------------ .../GradlePluginDevelopmentBasePlugin.java | 23 ++++- .../GroovyGradlePluginDevelopmentPlugin.java | 10 +- .../JavaGradlePluginDevelopmentPlugin.java | 10 +- .../RegisterCompatibilityExtension.java | 36 ------- ...CompatibilityInformationIfPresentRule.java | 40 ++++++++ .../internal/rules/CompatibilityGroup.java | 4 + ...entionBasedOnMinimumGradleVersionRule.java | 31 ++++++ .../rules/ConfigureJvmCompatibilityRule.java | 97 +++++++++++++++++++ ...onventionWithCurrentGradleVersionRule.java | 24 +++++ .../rules/ExternalGradleApiGroup.java | 4 + .../FinalizeCompatibilityExtensionRule.java | 19 ++++ ...FinalizeJvmCompatibilityExtensionRule.java | 20 ++++ .../rules/JvmCompatibilityExtension.java | 18 ++++ ...nGradlePluginDevelopmentExtensionRule.java | 20 ++++ ...pendencyFromMainApiConfigurationRule.java} | 15 +-- ...nDevelopmentBasePluginIntegrationTest.java | 3 + ...teMinimumGradleVersionIntegrationTest.java | 14 ++- ...ormationIfPresentRuleIntegrationTests.java | 58 +++++++++++ ...imumGradleVersionRuleIntegrationTests.java | 46 +++++++++ ...eJvmCompatibilityRuleIntegrationTests.java | 97 +++++++++++++++++++ ...rentGradleVersionRuleIntegrationTests.java | 37 +++++++ ...tibilityExtensionRuleIntegrationTests.java | 38 ++++++++ ...tibilityExtensionRuleIntegrationTests.java | 39 ++++++++ ...elopmentExtensionRuleIntegrationTests.java | 48 +++++++++ ...nApiConfigurationRuleIntegrationTests.java | 30 ++++++ 32 files changed, 738 insertions(+), 163 deletions(-) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/RuleGroup.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/AddGradleApiDependencyToCompileOnlyApiConfiguration.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/DefaultGradlePluginDevelopmentCompatibilityExtension.java delete mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RegisterCompatibilityExtension.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/CompatibilityGroup.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ExternalGradleApiGroup.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/JvmCompatibilityExtension.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule.java rename subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/{plugins/RemoveGradleApiProjectDependency.java => rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule.java} (63%) create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRuleIntegrationTests.java diff --git a/subprojects/gradle-plugin-development/src/functionalTest/groovy/dev/gradleplugins/GradlePluginDevelopmentExtensionFunctionalTest.groovy b/subprojects/gradle-plugin-development/src/functionalTest/groovy/dev/gradleplugins/GradlePluginDevelopmentExtensionFunctionalTest.groovy index 55c99db6..04e179c4 100644 --- a/subprojects/gradle-plugin-development/src/functionalTest/groovy/dev/gradleplugins/GradlePluginDevelopmentExtensionFunctionalTest.groovy +++ b/subprojects/gradle-plugin-development/src/functionalTest/groovy/dev/gradleplugins/GradlePluginDevelopmentExtensionFunctionalTest.groovy @@ -145,7 +145,7 @@ abstract class AbstractGradlePluginDevelopmentExtensionFunctionalTest extends Ab expect: fails('help') failure.assertHasDescription("A problem occurred configuring root project 'gradle-plugin'.") - failure.assertHasCause("The value for property 'minimumGradleVersion' cannot be changed any further.") + failure.assertHasCause("The value for extension 'compatibility' property 'minimumGradleVersion' cannot be changed any further.") } def "can generate Javadoc Jar"() { diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java index e5d4b70e..08ac5ff0 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/DefaultGradlePluginDevelopmentTestSuiteFactory.java @@ -1,7 +1,6 @@ package dev.gradleplugins; import dev.gradleplugins.internal.ConfigurePluginUnderTestMetadataTask; -import dev.gradleplugins.internal.FinalizableComponent; import dev.gradleplugins.internal.GradlePluginDevelopmentTestSuiteInternal; import dev.gradleplugins.internal.ReleasedVersionDistributions; import lombok.val; @@ -19,6 +18,7 @@ import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.ProviderUtils.finalizeValueOnRead; import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; final class DefaultGradlePluginDevelopmentTestSuiteFactory implements GradlePluginDevelopmentTestSuiteFactory { @@ -86,8 +86,7 @@ private static Provider minimumGradleVersion(Project project) { private static Provider ofDevelMinimumGradleVersionIfAvailable(Project project) { return project.provider(() -> { if (project.getPluginManager().hasPlugin("java-gradle-plugin") && project.getPluginManager().hasPlugin("dev.gradleplugins.gradle-plugin-base")) { - ((FinalizableComponent) compatibility(gradlePlugin(project))).finalizeComponent(); - return compatibility(gradlePlugin(project)).getMinimumGradleVersion(); + return finalizeValueOnRead(compatibility(gradlePlugin(project)).getMinimumGradleVersion()); } else { return Providers.notDefined(); // no minimum Gradle version... } diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentDependencyExtensionInternal.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentDependencyExtensionInternal.java index 47a15fd7..8eeb1b54 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentDependencyExtensionInternal.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentDependencyExtensionInternal.java @@ -1,6 +1,7 @@ package dev.gradleplugins.internal; import dev.gradleplugins.GradlePluginDevelopmentDependencyExtension; +import org.gradle.api.Project; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.dsl.DependencyHandler; @@ -76,6 +77,10 @@ public static GradlePluginDevelopmentDependencyExtensionInternal of(DependencyHa return (GradlePluginDevelopmentDependencyExtensionInternal) ExtensionAware.class.cast(dependencies).getExtensions().getByType(GradlePluginDevelopmentDependencyExtension.class); } + public static GradlePluginDevelopmentDependencyExtensionInternal forProject(Project project) { + return new GradlePluginDevelopmentDependencyExtensionInternal(project.getDependencies(), GradlePluginDevelopmentDependencyExtension.from(project.getDependencies()), project.getConfigurations(), DependencyFactory.forProject(project)); + } + @Override public TypeOf getPublicType() { return TypeOf.typeOf(GradlePluginDevelopmentDependencyExtension.class); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentExtensionInternal.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentExtensionInternal.java index 304c14e8..99debff4 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentExtensionInternal.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/GradlePluginDevelopmentExtensionInternal.java @@ -1,7 +1,7 @@ package dev.gradleplugins.internal; -import dev.gradleplugins.GroovyGradlePluginDevelopmentExtension; -import dev.gradleplugins.JavaGradlePluginDevelopmentExtension; +import dev.gradleplugins.internal.plugins.GroovyGradlePluginDevelopmentPlugin; +import dev.gradleplugins.internal.plugins.JavaGradlePluginDevelopmentPlugin; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; @@ -17,8 +17,6 @@ import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.plugins.internal.JavaConfigurationVariantMapping; -import org.gradle.api.provider.Property; -import org.gradle.api.provider.ProviderFactory; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.javadoc.Groovydoc; @@ -28,7 +26,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; -public abstract class GradlePluginDevelopmentExtensionInternal implements GroovyGradlePluginDevelopmentExtension, JavaGradlePluginDevelopmentExtension { +public abstract class GradlePluginDevelopmentExtensionInternal implements GroovyGradlePluginDevelopmentPlugin.LanguageExtensionInternal, JavaGradlePluginDevelopmentPlugin.LanguageExtensionInternal { private final JavaPluginExtension java; private boolean defaultRepositoriesDisabled = System.getProperty("dev.gradleplugins.default-repositories", "enabled").equals("disabled"); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/RuleGroup.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/RuleGroup.java new file mode 100644 index 00000000..a43b094d --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/RuleGroup.java @@ -0,0 +1,5 @@ +package dev.gradleplugins.internal; + +public @interface RuleGroup { + Class value(); +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/AddGradleApiDependencyToCompileOnlyApiConfiguration.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/AddGradleApiDependencyToCompileOnlyApiConfiguration.java deleted file mode 100644 index 23a8c032..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/AddGradleApiDependencyToCompileOnlyApiConfiguration.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.gradleplugins.internal.plugins; - -import dev.gradleplugins.internal.GradlePluginDevelopmentDependencyExtensionInternal; -import lombok.val; -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.plugins.AppliedPlugin; -import org.gradle.util.GradleVersion; - -import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; - -public final class AddGradleApiDependencyToCompileOnlyApiConfiguration implements Action { - private final Project project; - - public AddGradleApiDependencyToCompileOnlyApiConfiguration(Project project) { - this.project = project; - } - - @Override - public void execute(AppliedPlugin ignored) { - val dependencies = GradlePluginDevelopmentDependencyExtensionInternal.of(project.getDependencies()); - dependencies.add(getCompileOnlyApiConfigurationName(), compatibility(gradlePlugin(project)).getGradleApiVersion().map(dependencies::gradleApi)); - } - - private static String getCompileOnlyApiConfigurationName() { - if (GradleVersion.current().compareTo(GradleVersion.version("6.7")) >= 0) { - return "compileOnlyApi"; - } - return "compileOnly"; - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/DefaultGradlePluginDevelopmentCompatibilityExtension.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/DefaultGradlePluginDevelopmentCompatibilityExtension.java deleted file mode 100644 index 00a944cb..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/DefaultGradlePluginDevelopmentCompatibilityExtension.java +++ /dev/null @@ -1,63 +0,0 @@ -package dev.gradleplugins.internal.plugins; - -import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; -import dev.gradleplugins.internal.FinalizableComponent; -import dev.gradleplugins.internal.jvm.JvmCompatibilityProperties; -import dev.gradleplugins.internal.jvm.JvmCompatibilityPropertyFactory; -import org.gradle.api.Transformer; -import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.reflect.HasPublicType; -import org.gradle.api.reflect.TypeOf; -import org.gradle.util.GradleVersion; - -import javax.inject.Inject; - -import static dev.gradleplugins.GradlePluginDevelopmentDependencyExtension.GRADLE_API_LOCAL_VERSION; -import static dev.gradleplugins.GradleRuntimeCompatibility.minimumJavaVersionFor; -import static org.gradle.util.VersionNumber.parse; - -@SuppressWarnings("UnstableApiUsage") -abstract /*final*/ class DefaultGradlePluginDevelopmentCompatibilityExtension implements GradlePluginDevelopmentCompatibilityExtension, HasPublicType, FinalizableComponent { - private final JvmCompatibilityProperties compatibilities; - private boolean finalized = false; - - @Inject - public DefaultGradlePluginDevelopmentCompatibilityExtension(JavaPluginExtension java) { - this.compatibilities = JvmCompatibilityPropertyFactory.of(java); - getGradleApiVersion().convention(getMinimumGradleVersion().map(toLocalIfGradleSnapshotVersion())); - } - - private static Transformer toLocalIfGradleSnapshotVersion() { - return it -> { - if (GradleVersion.version(it).isSnapshot()) { - return GRADLE_API_LOCAL_VERSION; - } - return it; - }; - } - - @Override - public TypeOf getPublicType() { - return TypeOf.typeOf(GradlePluginDevelopmentCompatibilityExtension.class); - } - - @Override - public void finalizeComponent() { - if (!finalized) { - finalized = true; - if (getMinimumGradleVersion().isPresent()) { - compatibilities.set(minimumJavaVersionFor(parse(getMinimumGradleVersion().get()))); - } else { - getMinimumGradleVersion().set(GradleVersion.current().getVersion()); - } - getMinimumGradleVersion().disallowChanges(); - getGradleApiVersion().disallowChanges(); - compatibilities.finalizeValues(); - } - } - - @Override - public boolean isFinalized() { - return finalized; - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java index 31b8e824..8ea3676f 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java @@ -1,10 +1,18 @@ package dev.gradleplugins.internal.plugins; +import dev.gradleplugins.internal.rules.AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule; +import dev.gradleplugins.internal.rules.ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule; +import dev.gradleplugins.internal.rules.ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule; +import dev.gradleplugins.internal.rules.FinalizeCompatibilityExtensionRule; +import dev.gradleplugins.internal.rules.RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule; +import dev.gradleplugins.internal.rules.RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule; import org.gradle.api.Plugin; import org.gradle.api.Project; import javax.inject.Inject; +import static dev.gradleplugins.internal.util.ActionUtils.withoutParameter; + abstract /*final*/ class GradlePluginDevelopmentBasePlugin implements Plugin { @Inject public GradlePluginDevelopmentBasePlugin() {} @@ -12,9 +20,18 @@ public GradlePluginDevelopmentBasePlugin() {} @Override public void apply(Project project) { project.getPluginManager().apply(GradlePluginDevelopmentExtensionPlugin.class); - project.getPluginManager().withPlugin("java-gradle-plugin", new RegisterCompatibilityExtension(project)); - project.getPluginManager().withPlugin("java-gradle-plugin", new RemoveGradleApiProjectDependency(project)); - project.getPluginManager().withPlugin("java-gradle-plugin", new AddGradleApiDependencyToCompileOnlyApiConfiguration(project)); + project.getPluginManager().withPlugin("java-gradle-plugin", withoutParameter(() -> { + new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule().execute(project); + + new RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule().execute(project); + new ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule().execute(project); + + project.afterEvaluate(withoutParameter(() -> { + new AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule().execute(project); + new ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule().execute(project); + new FinalizeCompatibilityExtensionRule().execute(project); + })); + })); project.getPluginManager().withPlugin("java-gradle-plugin", new RemoveTestSourceSets(project)); } } diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GroovyGradlePluginDevelopmentPlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GroovyGradlePluginDevelopmentPlugin.java index 4c3e3fcb..f0cab4c4 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GroovyGradlePluginDevelopmentPlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GroovyGradlePluginDevelopmentPlugin.java @@ -20,6 +20,9 @@ import dev.gradleplugins.GroovyGradlePluginDevelopmentExtension; import dev.gradleplugins.internal.DeferredRepositoryFactory; import dev.gradleplugins.internal.GradlePluginDevelopmentDependencyExtensionInternal; +import dev.gradleplugins.internal.rules.ConfigureJvmCompatibilityRule; +import dev.gradleplugins.internal.rules.FinalizeJvmCompatibilityExtensionRule; +import dev.gradleplugins.internal.rules.JvmCompatibilityExtension; import lombok.val; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -38,6 +41,7 @@ public void apply(Project project) { assertJavaGradlePluginIsNotPreviouslyApplied(project.getPluginManager(), PLUGIN_ID); assertKotlinDslPluginIsNeverApplied(project.getPluginManager(), PLUGIN_ID); + project.afterEvaluate(new FinalizeJvmCompatibilityExtensionRule()); project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-base"); project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-testing-base"); // Starting with Gradle 6.4, precompiled Groovy DSL plugins are available @@ -48,9 +52,11 @@ public void apply(Project project) { } project.getPluginManager().apply("groovy"); - val groovy = registerLanguageExtension(project, "groovy", GroovyGradlePluginDevelopmentExtension.class); + val groovy = registerLanguageExtension(project, "groovy", LanguageExtensionInternal.class); val extension = compatibility(gradlePlugin(project)); + new ConfigureJvmCompatibilityRule().execute(project); + // Configure the Groovy version and dependency groovy.getGroovyVersion().convention(extension.getMinimumGradleVersion().map(GradleRuntimeCompatibility::groovyVersionOf)); val dependencies = GradlePluginDevelopmentDependencyExtensionInternal.of(project.getDependencies()); @@ -66,4 +72,6 @@ public void apply(Project project) { // We could also check that no plugin id on `gradlePlugin` container points to a Java source // We could do the same for Kotlin code } + + public interface LanguageExtensionInternal extends GroovyGradlePluginDevelopmentExtension, JvmCompatibilityExtension {} } \ No newline at end of file diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/JavaGradlePluginDevelopmentPlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/JavaGradlePluginDevelopmentPlugin.java index 020010f3..89459a78 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/JavaGradlePluginDevelopmentPlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/JavaGradlePluginDevelopmentPlugin.java @@ -17,6 +17,9 @@ package dev.gradleplugins.internal.plugins; import dev.gradleplugins.JavaGradlePluginDevelopmentExtension; +import dev.gradleplugins.internal.rules.ConfigureJvmCompatibilityRule; +import dev.gradleplugins.internal.rules.FinalizeJvmCompatibilityExtensionRule; +import dev.gradleplugins.internal.rules.JvmCompatibilityExtension; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -31,10 +34,15 @@ public void apply(Project project) { assertJavaGradlePluginIsNotPreviouslyApplied(project.getPluginManager(), PLUGIN_ID); assertKotlinDslPluginIsNeverApplied(project.getPluginManager(), PLUGIN_ID); + project.afterEvaluate(new FinalizeJvmCompatibilityExtensionRule()); project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-base"); project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-testing-base"); project.getPluginManager().apply("java-gradle-plugin"); // For plugin development - registerLanguageExtension(project, "java", JavaGradlePluginDevelopmentExtension.class); + registerLanguageExtension(project, "java", LanguageExtensionInternal.class); + + new ConfigureJvmCompatibilityRule().execute(project); } + + public interface LanguageExtensionInternal extends JavaGradlePluginDevelopmentExtension, JvmCompatibilityExtension {} } \ No newline at end of file diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RegisterCompatibilityExtension.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RegisterCompatibilityExtension.java deleted file mode 100644 index d0ac5238..00000000 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RegisterCompatibilityExtension.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.gradleplugins.internal.plugins; - -import lombok.val; -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.plugins.AppliedPlugin; -import org.gradle.api.plugins.ExtensionAware; - -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; -import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; - -final class RegisterCompatibilityExtension implements Action { - private static final String EXTENSION_NAME = "compatibility"; - private final Project project; - - RegisterCompatibilityExtension(Project project) { - this.project = project; - } - - @Override - public void execute(AppliedPlugin ignored) { - val extension = newCompatibilityExtension(); - - ((ExtensionAware) gradlePlugin(project)).getExtensions().add(EXTENSION_NAME, extension); - - project.afterEvaluate(finalize(extension)); - } - - private DefaultGradlePluginDevelopmentCompatibilityExtension newCompatibilityExtension() { - return project.getObjects().newInstance(DefaultGradlePluginDevelopmentCompatibilityExtension.class, java(project)); - } - - private static Action finalize(DefaultGradlePluginDevelopmentCompatibilityExtension extension) { - return ignored -> extension.finalizeComponent(); - } -} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule.java new file mode 100644 index 00000000..1d4ee47a --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule.java @@ -0,0 +1,40 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import dev.gradleplugins.internal.GradlePluginDevelopmentDependencyExtensionInternal; +import dev.gradleplugins.internal.RuleGroup; +import lombok.val; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.provider.Provider; +import org.gradle.plugin.devel.GradlePluginDevelopmentExtension; +import org.gradle.util.GradleVersion; + +import java.util.Optional; + +import static dev.gradleplugins.internal.util.SourceSetUtils.compileOnlyApiConfigurationName; + +@RuleGroup(ExternalGradleApiGroup.class) +// Finalizer rule because if rely on pluginSourceSet which may not be `main` +public final class AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule implements Action { + @Override + public void execute(Project project) { + final String configurationName = compileOnlyApiConfigurationName(gradlePlugin(project).getPluginSourceSet()); + val dependencies = GradlePluginDevelopmentDependencyExtensionInternal.forProject(project); + final Provider notation = project.provider(() -> compatibility(gradlePlugin(project)).orElse(null)) + .flatMap(GradlePluginDevelopmentCompatibilityExtension::getGradleApiVersion) + .orElse(GradleVersion.current().getVersion()) + .map(dependencies::gradleApi); + dependencies.add(configurationName, notation); + } + + private static GradlePluginDevelopmentExtension gradlePlugin(Project project) { + return (GradlePluginDevelopmentExtension) project.getExtensions().getByName("gradlePlugin"); + } + + private static Optional compatibility(GradlePluginDevelopmentExtension extension) { + return Optional.ofNullable((GradlePluginDevelopmentCompatibilityExtension) ((ExtensionAware) extension).getExtensions().findByName("compatibility")); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/CompatibilityGroup.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/CompatibilityGroup.java new file mode 100644 index 00000000..1f78cc71 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/CompatibilityGroup.java @@ -0,0 +1,4 @@ +package dev.gradleplugins.internal.rules; + +public interface CompatibilityGroup { +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule.java new file mode 100644 index 00000000..4599c164 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule.java @@ -0,0 +1,31 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import lombok.val; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.Transformer; +import org.gradle.util.GradleVersion; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.GradlePluginDevelopmentDependencyExtension.GRADLE_API_LOCAL_VERSION; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; + +@RuleGroup(CompatibilityGroup.class) +public final class ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule implements Action { + @Override + public void execute(Project project) { + val extension = compatibility(gradlePlugin(project)); + extension.getGradleApiVersion().convention(extension.getMinimumGradleVersion().map(toLocalIfGradleSnapshotVersion()) + .orElse("local")); + } + + private static Transformer toLocalIfGradleSnapshotVersion() { + return it -> { + if (GradleVersion.version(it).isSnapshot()) { + return GRADLE_API_LOCAL_VERSION; + } + return it; + }; + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRule.java new file mode 100644 index 00000000..08b7c916 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRule.java @@ -0,0 +1,97 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.JavaVersion; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.provider.Provider; +import org.gradle.plugin.devel.GradlePluginDevelopmentExtension; + +import java.util.Optional; +import java.util.concurrent.Callable; + +import static dev.gradleplugins.GradleRuntimeCompatibility.minimumJavaVersionFor; +import static dev.gradleplugins.internal.rules.JvmCompatibilityExtension.jvm; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static org.gradle.util.VersionNumber.parse; + +@RuleGroup(CompatibilityGroup.class) +public final class ConfigureJvmCompatibilityRule implements Action { + @Override + public void execute(Project project) { + // Ordering is important here + jvm(gradlePlugin(project)).getTargetCompatibility() + .value(compatibilityOf(project, targetCompatibility(java(project)))) + .finalizeValueOnRead(); + jvm(gradlePlugin(project)).getSourceCompatibility() + .value(compatibilityOf(project, sourceCompatibility(java(project)))) + .finalizeValueOnRead(); + } + + private static Provider compatibilityOf(Project project, JvmCompatibilityProperty delegate) { + final Provider minimumJavaVersion = project.provider(() -> compatibility(gradlePlugin(project)).orElse(null)) + .flatMap(GradlePluginDevelopmentCompatibilityExtension::getMinimumGradleVersion) + .map(it -> minimumJavaVersionFor(parse(it))); + return project.provider(toValue(delegate)).orElse(minimumJavaVersion).orElse(defaultValue(delegate)); + } + + private interface JvmCompatibilityProperty { + void set(JavaVersion value); + JavaVersion get(); + } + + private static JvmCompatibilityProperty sourceCompatibility(JavaPluginExtension extension) { + return new JvmCompatibilityProperty() { + @Override + public void set(JavaVersion value) { + extension.setSourceCompatibility(value); + } + + @Override + public JavaVersion get() { + return extension.getSourceCompatibility(); + } + }; + } + + private static JvmCompatibilityProperty targetCompatibility(JavaPluginExtension extension) { + return new JvmCompatibilityProperty() { + @Override + public void set(JavaVersion value) { + extension.setTargetCompatibility(value); + } + + @Override + public JavaVersion get() { + return extension.getTargetCompatibility(); + } + }; + } + + private static Callable toValue(JvmCompatibilityProperty property) { + return () -> { + final JavaVersion value = property.get(); + if (value.equals(JavaVersion.VERSION_1_1)) { + return null; // assume Java 1.1 as unset, continue the orElse chain + } else { + return value; + } + }; + } + + private static JavaVersion defaultValue(JvmCompatibilityProperty property) { + try { + return property.get(); + } finally { + property.set(JavaVersion.VERSION_1_1); + } + } + + private static Optional compatibility(GradlePluginDevelopmentExtension extension) { + return Optional.ofNullable((GradlePluginDevelopmentCompatibilityExtension) ((ExtensionAware) extension).getExtensions().findByName("compatibility")); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule.java new file mode 100644 index 00000000..69c07b7c --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule.java @@ -0,0 +1,24 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import dev.gradleplugins.internal.util.GradleUtils; +import lombok.val; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.util.GradleVersion; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradleUtils.currentGradleVersion; + +@RuleGroup(CompatibilityGroup.class) +// Finalizer rule because it sets a value to the minimum Gradle version +// must run before FinalizeCompatibilityExtensionRule +// must run after FinalizeJvmCompatibilityExtensionRule +public final class ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule implements Action { + @Override + public void execute(Project project) { + val extension = compatibility(gradlePlugin(project)); + extension.getMinimumGradleVersion().convention(currentGradleVersion().getVersion()); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ExternalGradleApiGroup.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ExternalGradleApiGroup.java new file mode 100644 index 00000000..c201ea0f --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ExternalGradleApiGroup.java @@ -0,0 +1,4 @@ +package dev.gradleplugins.internal.rules; + +public interface ExternalGradleApiGroup { +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRule.java new file mode 100644 index 00000000..19915f01 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRule.java @@ -0,0 +1,19 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.ProviderUtils.disallowChanges; + +@RuleGroup(CompatibilityGroup.class) +// Finalizer rule because it fixes the value of extension properties +public final class FinalizeCompatibilityExtensionRule implements Action { + @Override + public void execute(Project project) { + disallowChanges(compatibility(gradlePlugin(project)).getMinimumGradleVersion()); + disallowChanges(compatibility(gradlePlugin(project)).getGradleApiVersion()); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRule.java new file mode 100644 index 00000000..c5616c1e --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRule.java @@ -0,0 +1,20 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.internal.rules.JvmCompatibilityExtension.jvm; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static dev.gradleplugins.internal.util.ProviderUtils.finalizeValue; + +@RuleGroup(CompatibilityGroup.class) +// Finalizer rule because it sync the values for source/target compatibility on extension +public final class FinalizeJvmCompatibilityExtensionRule implements Action { + @Override + public void execute(Project project) { + java(project).setSourceCompatibility(finalizeValue(jvm(gradlePlugin(project)).getSourceCompatibility()).get()); + java(project).setTargetCompatibility(finalizeValue(jvm(gradlePlugin(project)).getTargetCompatibility()).get()); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/JvmCompatibilityExtension.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/JvmCompatibilityExtension.java new file mode 100644 index 00000000..e3690d7e --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/JvmCompatibilityExtension.java @@ -0,0 +1,18 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.JavaVersion; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.provider.Property; +import org.gradle.plugin.devel.GradlePluginDevelopmentExtension; + +import java.util.Objects; + +public interface JvmCompatibilityExtension { + Property getSourceCompatibility(); + Property getTargetCompatibility(); + + static JvmCompatibilityExtension jvm(GradlePluginDevelopmentExtension extension) { + Objects.requireNonNull(extension); + return ((ExtensionAware) extension).getExtensions().getByType(JvmCompatibilityExtension.class); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule.java new file mode 100644 index 00000000..b015328f --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule.java @@ -0,0 +1,20 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; + +@RuleGroup(CompatibilityGroup.class) +public final class RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule implements Action { + private static final String EXTENSION_NAME = "compatibility"; + + @Override + public void execute(Project project) { + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .create(EXTENSION_NAME, GradlePluginDevelopmentCompatibilityExtension.class); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RemoveGradleApiProjectDependency.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule.java similarity index 63% rename from subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RemoveGradleApiProjectDependency.java rename to subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule.java index bbe0f335..94220592 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/RemoveGradleApiProjectDependency.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule.java @@ -1,19 +1,14 @@ -package dev.gradleplugins.internal.plugins; +package dev.gradleplugins.internal.rules; +import dev.gradleplugins.internal.RuleGroup; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInternal; -import org.gradle.api.plugins.AppliedPlugin; - -final class RemoveGradleApiProjectDependency implements Action { - private final Project project; - - RemoveGradleApiProjectDependency(Project project) { - this.project = project; - } +@RuleGroup(ExternalGradleApiGroup.class) +public final class RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule implements Action { @Override - public void execute(AppliedPlugin ignored) { + public void execute(Project project) { // Surgical procedure of removing the Gradle API and replacing it with dev.gradleplugins:gradle-api project.getConfigurations().getByName("api").getDependencies().removeIf(it -> { if (it instanceof SelfResolvingDependencyInternal) { diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentBasePluginIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentBasePluginIntegrationTest.java index 89d2f6cc..73e37267 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentBasePluginIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentBasePluginIntegrationTest.java @@ -3,6 +3,7 @@ import org.gradle.api.Project; import org.gradle.api.artifacts.ExternalDependency; import org.gradle.api.artifacts.SelfResolvingDependency; +import org.gradle.api.internal.project.ProjectInternal; import org.gradle.testfixtures.ProjectBuilder; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,6 +37,7 @@ void removesSelfResolvingGradleApiDependency() { @Test void addsExternalGradleApiDependencyForMinimumGradleVersionToCompileOnlyApiIfAvailable() { + ((ProjectInternal) project).evaluate(); assumeTrue(project.getConfigurations().findByName("compileOnlyApi") != null); assertThat(project.getConfigurations().getByName("compileOnlyApi").getDependencies(), hasItem(allOf(isA(ExternalDependency.class), coordinate("dev.gradleplugins:gradle-api:6.5")))); @@ -43,6 +45,7 @@ void addsExternalGradleApiDependencyForMinimumGradleVersionToCompileOnlyApiIfAva @Test void addsExternalGradleApiDependencyForMinimumGradleVersionToCompileOnlyIfCompileOnlyApiIsNotAvailable() { + ((ProjectInternal) project).evaluate(); assumeTrue(project.getConfigurations().findByName("compileOnlyApi") == null); assertThat(project.getConfigurations().getByName("compileOnly").getDependencies(), hasItem(allOf(isA(ExternalDependency.class), coordinate("dev.gradleplugins:gradle-api:6.5")))); diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java index f95f271c..022114c0 100644 --- a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest.java @@ -1,7 +1,8 @@ package dev.gradleplugins; -import dev.gradleplugins.internal.FinalizableComponent; +import dev.gradleplugins.internal.util.GradleTestUtils; import org.gradle.api.Project; +import org.gradle.api.internal.project.ProjectInternal; import org.gradle.testfixtures.ProjectBuilder; import org.gradle.util.GradleVersion; import org.junit.jupiter.api.BeforeEach; @@ -15,7 +16,8 @@ import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class GradlePluginDevelopmentTestSuiteMinimumGradleVersionIntegrationTest { private final Project project = ProjectBuilder.builder().build(); @@ -44,6 +46,8 @@ class FinalizeTestedDevelComponentTest { void appliesCoreDevelComponentPlugins() { project.getPluginManager().apply("dev.gradleplugins.gradle-plugin-base"); project.getPluginManager().apply("java-gradle-plugin"); + GradleTestUtils.setCurrentGradleVersion(GradleVersion.version("6.2.1")); + ((ProjectInternal) project).evaluate(); } @Test @@ -51,12 +55,6 @@ void calculatesDefaultCompatibilityMinimumGradleVersionOnDevelWhenTestingStrateg assertThat(subject.getStrategies().getCoverageForMinimumVersion().getVersion(), equalTo(GradleVersion.current().getVersion())); assertThat(compatibility(gradlePlugin(project)).getMinimumGradleVersion(), providerOf(GradleVersion.current().getVersion())); } - - @Test - void finalizesCompatibilityExtensionWhenTestingStrategyQueried() { - subject.getStrategies().getCoverageForMinimumVersion().getVersion(); - assertTrue(((FinalizableComponent) compatibility(gradlePlugin(project))).isFinalized()); - } } @Nested diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRuleIntegrationTests.java new file mode 100644 index 00000000..334f0baa --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRuleIntegrationTests.java @@ -0,0 +1,58 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import dev.gradleplugins.internal.util.GradleTestUtils; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.gradle.util.GradleVersion; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.ProjectMatchers.coordinate; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +@ExtendWith(MockitoExtension.class) +class AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + GradleTestUtils.setCurrentGradleVersion(GradleVersion.version("6.2.1")); + } + + @Test + void addsExternalGradleApiDependencyOnCompileOnlyConfigurationUsingCurrentGradleVersion() { + subject.execute(project); + + assertThat(project.getConfigurations().getByName("compileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:6.2.1"))); + } + + @Test + void addsExternalGradleApiDependencyOnCompileOnlyConfigurationUsingCompatibilityGradleApiVersion() { + ((ExtensionAware) gradlePlugin(project)).getExtensions().create("compatibility", GradlePluginDevelopmentCompatibilityExtension.class); + compatibility(gradlePlugin(project)).getGradleApiVersion().set("6.8"); + subject.execute(project); + + assertThat(project.getConfigurations().getByName("compileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:6.8"))); + } + + @Test + void addsExternalGradleApiDependencyOnCompileOnlyConfigurationUsingCurrentGradleApiVersionWhenGradleApiVersionIsAbsent() { + ((ExtensionAware) gradlePlugin(project)).getExtensions().create("compatibility", GradlePluginDevelopmentCompatibilityExtension.class); + subject.execute(project); + + assertThat(project.getConfigurations().getByName("compileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:6.2.1"))); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRuleIntegrationTests.java new file mode 100644 index 00000000..af9f1078 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRuleIntegrationTests.java @@ -0,0 +1,46 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.hamcrest.MatcherAssert.assertThat; + +class ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .create("compatibility", GradlePluginDevelopmentCompatibilityExtension.class); + } + + @Test + void defaultsGradleApiVersionConventionToCurrentGradleVersion() { + subject.execute(project); + assertThat(compatibility(gradlePlugin(project)).getGradleApiVersion().value((String) null), providerOf("local")); + } + + @Test + void defaultsGradleApiVersionConventionToMinimumGradleVersionWhenNonSnapshotVersion() { + subject.execute(project); + compatibility(gradlePlugin(project)).getMinimumGradleVersion().set("6.7"); + assertThat(compatibility(gradlePlugin(project)).getGradleApiVersion().value((String) null), providerOf("6.7")); + } + + @Test + void defaultsGradleApiVersionConventionToLocalVersionWhenMinimumGradleVersionIsSnapshotVersion() { + subject.execute(project); + compatibility(gradlePlugin(project)).getMinimumGradleVersion().set("7.6-20220916231956+0000"); + assertThat(compatibility(gradlePlugin(project)).getGradleApiVersion().value((String) null), providerOf("local")); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRuleIntegrationTests.java new file mode 100644 index 00000000..148fb29b --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureJvmCompatibilityRuleIntegrationTests.java @@ -0,0 +1,97 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.JavaVersion; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.rules.JvmCompatibilityExtension.jvm; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +class ConfigureJvmCompatibilityRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ConfigureJvmCompatibilityRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions().create("jvm", JvmCompatibilityExtension.class); + } + + @Nested + class SourceCompatibilityTests { + @Test + void setJavaPluginToVersion1_1() { + subject.execute(project); + assertThat(java(project).getSourceCompatibility(), equalTo(JavaVersion.VERSION_1_1)); + } + + @Test + void usesMinimumJavaVersionFromMinimumGradleVersionWhenAvailable() { + subject.execute(project); + new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule().execute(project); + compatibility(gradlePlugin(project)).getMinimumGradleVersion().set("4.2"); + + assertThat(jvm(gradlePlugin(project)).getSourceCompatibility(), providerOf(JavaVersion.VERSION_1_7)); + } + + @Test + void usesOriginalValueWhenNoMinimumGradleVersionAvailable() { + final JavaVersion originalValue = java(project).getSourceCompatibility(); + subject.execute(project); + + assertThat(jvm(gradlePlugin(project)).getSourceCompatibility(), providerOf(originalValue)); + } + + @Test + void usesJavaPluginExtensionValueWhenSet() { + subject.execute(project); + java(project).setSourceCompatibility(JavaVersion.VERSION_12); + + assertThat(jvm(gradlePlugin(project)).getSourceCompatibility(), providerOf(JavaVersion.VERSION_12)); + } + } + + @Nested + class TargetCompatibilityTests { + @Test + void setJavaPluginToVersion1_1() { + subject.execute(project); + assertThat(java(project).getTargetCompatibility(), equalTo(JavaVersion.VERSION_1_1)); + } + + @Test + void usesMinimumJavaVersionFromMinimumGradleVersionWhenAvailable() { + subject.execute(project); + new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule().execute(project); + compatibility(gradlePlugin(project)).getMinimumGradleVersion().set("4.2"); + + assertThat(jvm(gradlePlugin(project)).getTargetCompatibility(), providerOf(JavaVersion.VERSION_1_7)); + } + + @Test + void usesOriginalValueWhenNoMinimumGradleVersionAvailable() { + final JavaVersion originalValue = java(project).getTargetCompatibility(); + subject.execute(project); + + assertThat(jvm(gradlePlugin(project)).getTargetCompatibility(), providerOf(originalValue)); + } + + @Test + void usesJavaPluginExtensionValueWhenSet() { + subject.execute(project); + java(project).setTargetCompatibility(JavaVersion.VERSION_12); + + assertThat(jvm(gradlePlugin(project)).getTargetCompatibility(), providerOf(JavaVersion.VERSION_12)); + } + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRuleIntegrationTests.java new file mode 100644 index 00000000..a74812f9 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRuleIntegrationTests.java @@ -0,0 +1,37 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import dev.gradleplugins.internal.util.GradleTestUtils; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.gradle.util.GradleVersion; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.hamcrest.MatcherAssert.assertThat; + +class ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .create("compatibility", GradlePluginDevelopmentCompatibilityExtension.class); + } + + @Test + void defaultsMinimumGradleVersionConventionToCurrentGradleVersion() { + GradleTestUtils.setCurrentGradleVersion(GradleVersion.version("6.7")); + subject.execute(project); + compatibility(gradlePlugin(project)).getMinimumGradleVersion().set((String) null); + + assertThat(compatibility(gradlePlugin(project)).getMinimumGradleVersion().value((String) null), providerOf("6.7")); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRuleIntegrationTests.java new file mode 100644 index 00000000..067c91b1 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeCompatibilityExtensionRuleIntegrationTests.java @@ -0,0 +1,38 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class FinalizeCompatibilityExtensionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new FinalizeCompatibilityExtensionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions().create("compatibility", GradlePluginDevelopmentCompatibilityExtension.class); + } + + @Test + void disallowChangesOnMinimumGradleVersionProperty() { + subject.execute(project); + assertThrows(IllegalStateException.class, + () -> compatibility(gradlePlugin(project)).getMinimumGradleVersion().set((String) null)); + } + + @Test + void disallowChangesOnGradleApiVersionProperty() { + subject.execute(project); + assertThrows(IllegalStateException.class, + () -> compatibility(gradlePlugin(project)).getGradleApiVersion().set((String) null)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRuleIntegrationTests.java new file mode 100644 index 00000000..cbf2c69a --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/FinalizeJvmCompatibilityExtensionRuleIntegrationTests.java @@ -0,0 +1,39 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.JavaVersion; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +class FinalizeJvmCompatibilityExtensionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new FinalizeJvmCompatibilityExtensionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + final JvmCompatibilityExtension extension = ((ExtensionAware) gradlePlugin(project)).getExtensions().create("jvm", JvmCompatibilityExtension.class); + extension.getSourceCompatibility().set(JavaVersion.VERSION_12); + extension.getTargetCompatibility().set(JavaVersion.VERSION_1_9); + } + + @Test + void overwriteJavaExtensionSourceCompatibility() { + subject.execute(project); + assertThat(java(project).getSourceCompatibility(), equalTo(JavaVersion.VERSION_12)); + } + + @Test + void overwriteJavaExtensionTargetCompatibility() { + subject.execute(project); + assertThat(java(project).getTargetCompatibility(), equalTo(JavaVersion.VERSION_1_9)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRuleIntegrationTests.java new file mode 100644 index 00000000..dbcf36c5 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRuleIntegrationTests.java @@ -0,0 +1,48 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.GradlePluginDevelopmentCompatibilityExtension.compatibility; +import static dev.gradleplugins.ProjectMatchers.absentProvider; +import static dev.gradleplugins.ProjectMatchers.extensions; +import static dev.gradleplugins.ProjectMatchers.named; +import static dev.gradleplugins.ProjectMatchers.publicType; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; + +class RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + } + + @Test + void hasCompatibilityExtension() { + subject.execute(project); + assertThat(gradlePlugin(project), extensions(hasItem(allOf( + named("compatibility"), + publicType(GradlePluginDevelopmentCompatibilityExtension.class))))); + } + + @Test + void hasNoMinimumGradleVersionValue() { + subject.execute(project); + assertThat(compatibility(gradlePlugin(project)).getMinimumGradleVersion(), absentProvider()); + } + + @Test + void hasNoGradleApiVersionValue() { + subject.execute(project); + assertThat(compatibility(gradlePlugin(project)).getGradleApiVersion(), absentProvider()); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRuleIntegrationTests.java new file mode 100644 index 00000000..bf2d47dc --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRuleIntegrationTests.java @@ -0,0 +1,30 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.SelfResolvingDependency; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.isA; +import static org.hamcrest.Matchers.not; + +class RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + } + + @Test + void removesLocalGradleApiDependencyFromApiConfiguration() { + subject.execute(project); + assertThat(project.getConfigurations().getByName("api").getDependencies(), + not(hasItem(isA(SelfResolvingDependency.class)))); + } +} From db6f383377db0eeaa12ea7936a871fb2b4e1c2b2 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Mon, 19 Sep 2022 16:19:58 -0400 Subject: [PATCH 14/19] Prepare version 1.6.9 Signed-off-by: Daniel Lacasse --- README.adoc | 2 +- build.gradle | 4 ++-- .../gradle-plugin-development-test-fixtures/build.gradle | 2 +- subprojects/gradle-plugin-development/README.adoc | 2 +- subprojects/gradle-plugin-development/build.gradle | 2 +- .../dev/gradleplugins/internal/DefaultDependencyVersions.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.adoc b/README.adoc index 2a475fbb..5a17e822 100644 --- a/README.adoc +++ b/README.adoc @@ -1,4 +1,4 @@ -:jbake-version: 1.6.8 +:jbake-version: 1.6.9 // TODO: Add test for the version above = Gradle Plugin Development Toolbox diff --git a/build.gradle b/build.gradle index f62d3d81..0739d548 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { allprojects { group = 'dev.gradleplugins' } -version = '1.6.8' +version = '1.6.9' // Configure javadoc allprojects { @@ -19,7 +19,7 @@ allprojects { // Configure gradle-fixtures-* versions subprojects { if (project.name.startsWith('gradle-fixtures') || project.name.startsWith('gradle-runner-kit')) { - version = '0.0.138' + version = '0.0.139' } } diff --git a/subprojects/gradle-plugin-development-test-fixtures/build.gradle b/subprojects/gradle-plugin-development-test-fixtures/build.gradle index afa822d6..2924fccb 100644 --- a/subprojects/gradle-plugin-development-test-fixtures/build.gradle +++ b/subprojects/gradle-plugin-development-test-fixtures/build.gradle @@ -7,7 +7,7 @@ plugins { } description = 'Gradle plugin development plugins test fixtures.' -version = '1.6.8' +version = '1.6.9' dependencies { compileOnly gradleApi(minimumGradleVersion) diff --git a/subprojects/gradle-plugin-development/README.adoc b/subprojects/gradle-plugin-development/README.adoc index 47d18cfd..cfe56bdb 100644 --- a/subprojects/gradle-plugin-development/README.adoc +++ b/subprojects/gradle-plugin-development/README.adoc @@ -1,4 +1,4 @@ -:jbake-version: 1.6.8 +:jbake-version: 1.6.9 = Gradle Plugin Development Plugins The Gradle plugin development plugins are a set of plugins accelerating Gradle plugin development. diff --git a/subprojects/gradle-plugin-development/build.gradle b/subprojects/gradle-plugin-development/build.gradle index a01d63c2..65760a8f 100644 --- a/subprojects/gradle-plugin-development/build.gradle +++ b/subprojects/gradle-plugin-development/build.gradle @@ -11,7 +11,7 @@ apply plugin: 'dev.gradleplugins.gradle-plugin-unit-test' apply plugin: 'dev.gradleplugins.gradle-plugin-functional-test' description = 'Gradle plugin development plugins.' -version = '1.6.8' +version = '1.6.9' gradlePlugin { plugins { diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/DefaultDependencyVersions.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/DefaultDependencyVersions.java index d775ce69..a5d4e903 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/DefaultDependencyVersions.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/DefaultDependencyVersions.java @@ -5,5 +5,5 @@ public interface DefaultDependencyVersions { String SPOCK_FRAMEWORK_VERSION = "1.2-groovy-2.5"; @Deprecated String GROOVY_ALL_VERSION = "2.5.2"; // Align with Spock - String GRADLE_FIXTURES_VERSION = "0.0.138"; + String GRADLE_FIXTURES_VERSION = "0.0.139"; } From a272984ef1e9f8e0afe296eae663ec55b83d815e Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 20 Sep 2022 12:17:46 -0400 Subject: [PATCH 15/19] Add helper method to work with `addAllLater` collection method Signed-off-by: Daniel Lacasse --- .../util/DomainObjectCollectionUtils.java | 14 ++++++++++ ...ectCollectionUtils_SingleOrEmptyTests.java | 28 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_SingleOrEmptyTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java index 93548aca..dbd30da5 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/DomainObjectCollectionUtils.java @@ -1,8 +1,11 @@ package dev.gradleplugins.internal.util; import org.gradle.api.Action; +import org.gradle.api.provider.Provider; import org.gradle.api.specs.Spec; +import java.util.Collections; + public final class DomainObjectCollectionUtils { private DomainObjectCollectionUtils() {} @@ -13,4 +16,15 @@ public static Action matching(Spec spec, Action act } }; } + + /** + * Helper methods around {@link org.gradle.api.DomainObjectCollection#addAllLater} for optional element. + * + * @param self the optional element provider to add, must not be null + * @return an single-element or empty iterable provider, never null + * @param the element type + */ + public static Provider> singleOrEmpty(Provider self) { + return self.map(Collections::singletonList).orElse(Collections.emptyList()); + } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_SingleOrEmptyTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_SingleOrEmptyTests.java new file mode 100644 index 00000000..3718434d --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/DomainObjectCollectionUtils_SingleOrEmptyTests.java @@ -0,0 +1,28 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.provider.ProviderFactory; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.singleOrEmpty; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.emptyIterable; + +class DomainObjectCollectionUtils_SingleOrEmptyTests { + + @Test + void returnsEmptyIterableForAbsentProvider() { + assertThat(singleOrEmpty(providerFactory().provider(() -> null)), providerOf(emptyIterable())); + } + + @Test + void returnsIterableWithSingleElementForPresentProvider() { + assertThat(singleOrEmpty(providerFactory().provider(() -> "single")), providerOf(contains("single"))); + } + + private static ProviderFactory providerFactory() { + return ProjectBuilder.builder().build().getProviders(); + } +} From 85230dda7df2aeee8245d12862bf22e5a2539b15 Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 20 Sep 2022 12:18:32 -0400 Subject: [PATCH 16/19] Add helper method for transforming each element of an iterable provider Signed-off-by: Daniel Lacasse --- .../internal/util/ProviderUtils.java | 7 +++ .../ProviderUtils_TransformEachTests.java | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_TransformEachTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java index a74c424d..740432d1 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/ProviderUtils.java @@ -1,9 +1,12 @@ package dev.gradleplugins.internal.util; +import org.gradle.api.Transformer; import org.gradle.api.provider.HasConfigurableValue; import org.gradle.api.provider.Provider; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; public final class ProviderUtils { private ProviderUtils() {} @@ -32,4 +35,8 @@ public static void ifPresent(Provider self, Consumer action) { action.accept(value); } } + + public static > Transformer, ITERABLE> transformEach(Transformer transformer) { + return it -> StreamSupport.stream(it.spliterator(), false).map(transformer::transform).collect(Collectors.toList()); + } } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_TransformEachTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_TransformEachTests.java new file mode 100644 index 00000000..9508e08e --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/util/ProviderUtils_TransformEachTests.java @@ -0,0 +1,43 @@ +package dev.gradleplugins.internal.util; + +import org.gradle.api.Transformer; +import org.gradle.api.provider.Provider; +import org.gradle.api.provider.ProviderFactory; +import org.gradle.testfixtures.ProjectBuilder; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.List; + +import static dev.gradleplugins.ProjectMatchers.providerOf; +import static dev.gradleplugins.internal.util.ProviderUtils.transformEach; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.mockito.ArgumentMatchers.any; + +@ExtendWith(MockitoExtension.class) +class ProviderUtils_TransformEachTests { + Provider> subject = providerFactory().provider(() -> Arrays.asList("first", "second", "third")); + @Mock Transformer transformer; + + @Test + void transformEachElementsWhenProviderRealized() { + Mockito.when(transformer.transform(any())).thenAnswer(args -> "transformed-" + args.getArgument(0, String.class)); + assertThat(subject.map(transformEach(transformer)), providerOf(contains("transformed-first", "transformed-second", "transformed-third"))); + } + + @Test + void doesNotTransformEachElementsWhenProviderNotRealized() { + subject.map(transformEach(transformer)); + Mockito.verifyNoInteractions(transformer); + } + + private static ProviderFactory providerFactory() { + return ProjectBuilder.builder().build().getProviders(); + } +} From ba8bff065bd669aa7550b40004e59a93c7b550ed Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 20 Sep 2022 12:25:30 -0400 Subject: [PATCH 17/19] Add support for versioned source set (per Gradle version) Signed-off-by: Daniel Lacasse --- .../GradlePluginDevelopmentBasePlugin.java | 6 +++ .../rules/VersionedSourceSetGroup.java | 4 ++ .../rules/VersionedSourceSetUtils.java | 38 ++++++++++++++ ...igurationOfEachVersionedSourceSetRule.java | 42 +++++++++++++++ ...urceSetAsImplementationDependencyRule.java | 51 +++++++++++++++++++ ...mFeatureForEachVersionedSourceSetRule.java | 45 ++++++++++++++++ ...ersionedSourceSetRuleIntegrationTests.java | 39 ++++++++++++++ ...ntationDependencyRuleIntegrationTests.java | 45 ++++++++++++++++ ...ersionedSourceSetRuleIntegrationTests.java | 34 +++++++++++++ 9 files changed, 304 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetGroup.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRuleIntegrationTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java index 8ea3676f..33c50ed2 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java @@ -1,10 +1,13 @@ package dev.gradleplugins.internal.plugins; import dev.gradleplugins.internal.rules.AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule; +import dev.gradleplugins.internal.rules.VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule; +import dev.gradleplugins.internal.rules.VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule; import dev.gradleplugins.internal.rules.ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule; import dev.gradleplugins.internal.rules.ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule; import dev.gradleplugins.internal.rules.FinalizeCompatibilityExtensionRule; import dev.gradleplugins.internal.rules.RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule; +import dev.gradleplugins.internal.rules.VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule; import dev.gradleplugins.internal.rules.RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -22,14 +25,17 @@ public void apply(Project project) { project.getPluginManager().apply(GradlePluginDevelopmentExtensionPlugin.class); project.getPluginManager().withPlugin("java-gradle-plugin", withoutParameter(() -> { new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule().execute(project); + new VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule().execute(project); new RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule().execute(project); new ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule().execute(project); + new VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule().execute(project); project.afterEvaluate(withoutParameter(() -> { new AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule().execute(project); new ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule().execute(project); new FinalizeCompatibilityExtensionRule().execute(project); + new VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule().execute(project); })); })); project.getPluginManager().withPlugin("java-gradle-plugin", new RemoveTestSourceSets(project)); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetGroup.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetGroup.java new file mode 100644 index 00000000..9be4fddb --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetGroup.java @@ -0,0 +1,4 @@ +package dev.gradleplugins.internal.rules; + +public interface VersionedSourceSetGroup { +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java new file mode 100644 index 00000000..8f10e6b3 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java @@ -0,0 +1,38 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Project; +import org.gradle.api.Transformer; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ProjectDependency; +import org.gradle.api.specs.Spec; +import org.gradle.api.tasks.SourceSet; + +final class VersionedSourceSetUtils { + private VersionedSourceSetUtils() {} + + + static Spec isVersionedSourceSet() { + return it -> it.getName().startsWith("v"); + } + + // TODO: Move somewhere else + public static String capability(Project project, String name) { + return project.getGroup() + ":" + project.getName() + "-" + name + ":" + project.getVersion(); + } + + // TODO: Move somewhere else + public static Transformer asDependency(Project project) { + return capabilityName -> { + final ProjectDependency dependency = (ProjectDependency) project.getDependencies().create(project); + dependency.capabilities(capabilities -> { + capabilities.requireCapability(capability(project, capabilityName)); + }); + return dependency; + }; + } + + public static String gradleVersionClassifier(String gradleVersion) { + assert gradleVersion.startsWith("v"); + return "gradle-" + gradleVersion; + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule.java new file mode 100644 index 00000000..aca60a50 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule.java @@ -0,0 +1,42 @@ +/* + * Copyright 2022 the original author or authors. + * + * 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 + * + * https://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 dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.GradlePluginDevelopmentDependencyExtensionInternal; +import dev.gradleplugins.internal.RuleGroup; +import lombok.val; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.isVersionedSourceSet; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.matching; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; + +@RuleGroup(VersionedSourceSetGroup.class) +public final class VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule implements Action { + @Override + public void execute(Project project) { + sourceSets(project, it -> it.configureEach(matching(isVersionedSourceSet(), sourceSet -> { + val dependencies = GradlePluginDevelopmentDependencyExtensionInternal.forProject(project); + // NOTE: We use compileOnly instead of compileOnlyApi because no-one should build against those components + dependencies.add(sourceSet.getCompileOnlyConfigurationName(), dependencies.gradleApi(toGradleVersion(sourceSet.getName()))); + }))); + } + + private static String toGradleVersion(String name) { + return name.substring(1); // remove 'v' suffix + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule.java new file mode 100644 index 00000000..13bd4414 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule.java @@ -0,0 +1,51 @@ +/* + * Copyright 2022 the original author or authors. + * + * 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 + * + * https://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 dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.Transformer; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.tasks.SourceSet; + +import java.util.Collection; +import java.util.stream.Collectors; + +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.asDependency; +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.isVersionedSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.ProviderUtils.transformEach; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; + +@RuleGroup(VersionedSourceSetGroup.class) +// Finalizer rule because rely on pluginSourceSet which may or may not be `main` +public final class VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule implements Action { + @Override + public void execute(Project project) { + project.getConfigurations().named(gradlePlugin(project).getPluginSourceSet().getImplementationConfigurationName(), configuration -> { + configuration.getDependencies().addAllLater(project.getObjects().setProperty(Dependency.class) + .value(sourceSets(project).map(onlyVersionedSourceSet()) + .map(transformEach(SourceSet::getName)) + .map(transformEach(VersionedSourceSetUtils::gradleVersionClassifier)) + .map(transformEach(asDependency(project))))); + }); + } + + private static Transformer, Collection> onlyVersionedSourceSet() { + return sourceSets -> sourceSets.stream().filter(isVersionedSourceSet()::isSatisfiedBy).collect(Collectors.toList()); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule.java new file mode 100644 index 00000000..50f36ac9 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule.java @@ -0,0 +1,45 @@ +/* + * Copyright 2022 the original author or authors. + * + * 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 + * + * https://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 dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.jvm.tasks.Jar; + +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.gradleVersionClassifier; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.matching; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; + +@RuleGroup(VersionedSourceSetGroup.class) +public final class VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule implements Action { + @Override + public void execute(Project project) { + sourceSets(project, it -> it.configureEach(matching(VersionedSourceSetUtils.isVersionedSourceSet(), sourceSet -> { + java(project).registerFeature(toFeatureName(sourceSet.getName()), spec -> { + spec.usingSourceSet(sourceSet); + spec.capability(project.getGroup().toString(), project.getName() + "-" + gradleVersionClassifier(sourceSet.getName()), project.getVersion().toString()); + }); + project.getTasks().named(sourceSet.getJarTaskName(), Jar.class, + task -> task.getArchiveClassifier().set(gradleVersionClassifier(sourceSet.getName()))); + }))); + } + + private static String toFeatureName(String version) { + return version.replace(".", ""); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRuleIntegrationTests.java new file mode 100644 index 00000000..ca3fc7db --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRuleIntegrationTests.java @@ -0,0 +1,39 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.coordinate; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +class VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java"); + } + + @Test + void addsGradleApiDependencyToCompileOnly() { + subject.execute(project); + sourceSets(project, it -> { + it.create("v3.4"); + it.create("v6.9"); + it.create("v7.2.1"); + }); + + assertThat(project.getConfigurations().getByName("v34CompileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:3.4"))); + assertThat(project.getConfigurations().getByName("v69CompileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:6.9"))); + assertThat(project.getConfigurations().getByName("v721CompileOnly").getDependencies(), + hasItem(coordinate("dev.gradleplugins:gradle-api:7.2.1"))); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRuleIntegrationTests.java new file mode 100644 index 00000000..1d955cb6 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRuleIntegrationTests.java @@ -0,0 +1,45 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.capabilities; +import static dev.gradleplugins.ProjectMatchers.coordinate; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; + +class VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRuleIntegrationTests { + Project project = ProjectBuilder.builder().withName("foo").build(); + Action subject = new VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule(); + + @BeforeEach + void configureProject() { + project.setGroup("com.example"); + project.setVersion("5.2"); + project.getPluginManager().apply("java-gradle-plugin"); + sourceSets(project, it -> { + it.create("v6.5"); + it.create("v6.8"); + it.create("v7.0"); + gradlePlugin(project).pluginSourceSet(it.create("plugin")); + }); + } + + @Test + void addsImplementationDependencyOnEachVersionedComponents() { + subject.execute(project); + assertThat(project.getConfigurations().getByName("pluginImplementation").getDependencies(), + hasItems( + allOf(coordinate("com.example:foo:5.2"), capabilities(hasItem(coordinate("com.example:foo-gradle-v6.5:5.2")))), + allOf(coordinate("com.example:foo:5.2"), capabilities(hasItem(coordinate("com.example:foo-gradle-v6.8:5.2")))), + allOf(coordinate("com.example:foo:5.2"), capabilities(hasItem(coordinate("com.example:foo-gradle-v7.0:5.2")))) + )); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRuleIntegrationTests.java new file mode 100644 index 00000000..92f7f050 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRuleIntegrationTests.java @@ -0,0 +1,34 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.capabilities; +import static dev.gradleplugins.ProjectMatchers.coordinate; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +class VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRuleIntegrationTests { + Project project = ProjectBuilder.builder().withName("foo").build(); + Action subject = new VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule(); + + @BeforeEach + void configureProject() { + project.setGroup("com.example"); + project.setVersion("4.2"); + project.getPluginManager().apply("java-base"); + subject.execute(project); + } + + @Test + void registersFeatureForEachVersionedSourceSetWithCustomCapability() { + sourceSets(project, it -> it.create("v5.6")); + + assertThat(project.getConfigurations().getByName("v56ApiElements").getOutgoing(), + capabilities(hasItem(coordinate("com.example:foo-gradle-v5.6:4.2")))); + } +} From c0688049b140174978c093d1fc51baef83e8f6dc Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 20 Sep 2022 12:29:07 -0400 Subject: [PATCH 18/19] Introduce API source set for Gradle plugins Consumer of this plugin will only get the API classes when an API source set is declared. Signed-off-by: Daniel Lacasse --- .../GradlePluginDevelopmentBasePlugin.java | 10 ++++ .../internal/rules/ApiSourceSetGroup.java | 4 ++ ...ElementsWhenApiSourceSetAvailableRule.java | 19 +++++++ ...tensionPluginDevelopmentExtensionRule.java | 18 +++++++ ...nDependsOnApiSourceSetIfAvailableRule.java | 28 ++++++++++ ...urceSetAsJavaFeatureWhenAvailableRule.java | 24 +++++++++ ...nGradlePluginDevelopmentExtensionRule.java | 22 ++++++++ .../rules/VersionedSourceSetUtils.java | 5 ++ .../util/GradlePluginDevelopmentUtils.java | 8 +++ ...ourceSetAvailableRuleIntegrationTests.java | 34 ++++++++++++ ...elopmentExtensionRuleIntegrationTests.java | 32 ++++++++++++ ...rceSetIfAvailableRuleIntegrationTests.java | 52 +++++++++++++++++++ ...tureWhenAvailableRuleIntegrationTests.java | 47 +++++++++++++++++ ...elopmentExtensionRuleIntegrationTests.java | 52 +++++++++++++++++++ 14 files changed, 355 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSetGroup.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule.java create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRuleIntegrationTests.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRuleIntegrationTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java index 33c50ed2..6ac25515 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java @@ -1,11 +1,16 @@ package dev.gradleplugins.internal.plugins; import dev.gradleplugins.internal.rules.AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule; +import dev.gradleplugins.internal.rules.ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule; import dev.gradleplugins.internal.rules.VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule; import dev.gradleplugins.internal.rules.VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule; import dev.gradleplugins.internal.rules.ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule; import dev.gradleplugins.internal.rules.ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule; +import dev.gradleplugins.internal.rules.ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule; +import dev.gradleplugins.internal.rules.ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule; import dev.gradleplugins.internal.rules.FinalizeCompatibilityExtensionRule; +import dev.gradleplugins.internal.rules.ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule; +import dev.gradleplugins.internal.rules.ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule; import dev.gradleplugins.internal.rules.RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule; import dev.gradleplugins.internal.rules.VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule; import dev.gradleplugins.internal.rules.RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule; @@ -26,15 +31,20 @@ public void apply(Project project) { project.getPluginManager().withPlugin("java-gradle-plugin", withoutParameter(() -> { new RegisterCompatibilityExtensionGradlePluginDevelopmentExtensionRule().execute(project); new VersionedSourceSet_RegisterJvmFeatureForEachVersionedSourceSetRule().execute(project); + new ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule().execute(project); new RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule().execute(project); new ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule().execute(project); new VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule().execute(project); project.afterEvaluate(withoutParameter(() -> { + new ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule().execute(project); new AddGradleApiDependencyToCompileOnlyApiConfigurationUsingCompatibilityInformationIfPresentRule().execute(project); + new ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule().execute(project); + new ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule().execute(project); new ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule().execute(project); new FinalizeCompatibilityExtensionRule().execute(project); + new ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule().execute(project); new VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule().execute(project); })); })); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSetGroup.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSetGroup.java new file mode 100644 index 00000000..5f2684ed --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSetGroup.java @@ -0,0 +1,4 @@ +package dev.gradleplugins.internal.rules; + +public interface ApiSourceSetGroup { +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule.java new file mode 100644 index 00000000..425816c7 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule.java @@ -0,0 +1,19 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; + +@RuleGroup(ApiSourceSetGroup.class) +// Finalizer rule because it needs plugin source set +public class ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule implements Action { + @Override + public void execute(Project project) { + project.getConfigurations().named(gradlePlugin(project).getPluginSourceSet().getApiElementsConfigurationName(), configuration -> { + configuration.getOutgoing().getArtifacts().clear(); // clear base artifacts + configuration.getOutgoing().getVariants().clear(); // clear classes artifacts + }); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule.java new file mode 100644 index 00000000..28d8ebc8 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule.java @@ -0,0 +1,18 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.ProviderUtils.disallowChanges; + +@RuleGroup(ApiSourceSetGroup.class) +// Finalizer rule because it locks api source set +public final class ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule implements Action { + @Override + public void execute(Project project) { + disallowChanges(apiSourceSet(gradlePlugin(project))); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule.java new file mode 100644 index 00000000..21049e58 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule.java @@ -0,0 +1,28 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.tasks.SourceSet; + +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.apiClassifier; +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.asDependency; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.singleOrEmpty; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; + +@RuleGroup(ApiSourceSetGroup.class) +// Finalizer rule because it needs plugin source set +public class ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule implements Action { + @Override + public void execute(Project project) { + final SourceSet sourceSet = gradlePlugin(project).getPluginSourceSet(); + project.getConfigurations().named(sourceSet.getApiConfigurationName(), configuration -> { + configuration.getDependencies().addAllLater(project.getObjects().setProperty(Dependency.class) + .value(singleOrEmpty(apiSourceSet(gradlePlugin(project)) + .map(__ -> apiClassifier()) + .map(asDependency(project))))); + }); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule.java new file mode 100644 index 00000000..d1715a2d --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule.java @@ -0,0 +1,24 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static dev.gradleplugins.internal.util.ProviderUtils.ifPresent; + +@RuleGroup(ApiSourceSetGroup.class) +// Finalizer rule because the final value of apiSourceSet and pluginSourceSet is required +public final class ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule implements Action { + @Override + public void execute(Project project) { + ifPresent(apiSourceSet(gradlePlugin(project)), sourceSet -> { + // Maybe be another rule??? + java(project).registerFeature("api", spec -> { + spec.usingSourceSet(sourceSet); + }); + }); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule.java new file mode 100644 index 00000000..50a1c578 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule.java @@ -0,0 +1,22 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.provider.Property; +import org.gradle.api.reflect.TypeOf; +import org.gradle.api.tasks.SourceSet; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.ProviderUtils.finalizeValueOnRead; + +@RuleGroup(ApiSourceSetGroup.class) +public final class ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule implements Action { + @Override + public void execute(Project project) { + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .add(new TypeOf>() {}, "apiSourceSet", + finalizeValueOnRead(project.getObjects().property(SourceSet.class))); + } +} diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java index 8f10e6b3..9a15e383 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSetUtils.java @@ -20,6 +20,11 @@ public static String capability(Project project, String name) { return project.getGroup() + ":" + project.getName() + "-" + name + ":" + project.getVersion(); } + // TODO: Move somewhere else + public static String apiClassifier() { + return "api"; + } + // TODO: Move somewhere else public static Transformer asDependency(Project project) { return capabilityName -> { diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java index 1f09cd4b..35426d7e 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/util/GradlePluginDevelopmentUtils.java @@ -1,7 +1,10 @@ package dev.gradleplugins.internal.util; import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.SourceSet; import org.gradle.plugin.devel.GradlePluginDevelopmentExtension; public final class GradlePluginDevelopmentUtils { @@ -9,6 +12,11 @@ public static GradlePluginDevelopmentExtension gradlePlugin(Project project) { return project.getExtensions().getByType(GradlePluginDevelopmentExtension.class); } + @SuppressWarnings("unchecked") + public static Property apiSourceSet(GradlePluginDevelopmentExtension extension) { + return (Property) ((ExtensionAware) extension).getExtensions().getByName("apiSourceSet"); + } + public static JavaPluginExtension java(Project project) { return project.getExtensions().getByType(JavaPluginExtension.class); } diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRuleIntegrationTests.java new file mode 100644 index 00000000..cc051cfb --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRuleIntegrationTests.java @@ -0,0 +1,34 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyIterable; + +class ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ApiSourceSet_ClearPluginOutgoingApiElementsWhenApiSourceSetAvailableRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + gradlePlugin(project).pluginSourceSet(sourceSets(project).map(it -> it.maybeCreate("plugin")).get()); + java(project).registerFeature("plugin", spec -> spec.usingSourceSet(gradlePlugin(project).getPluginSourceSet())); + } + + @Test + void removesAllArtifactsOnApiElements() { + subject.execute(project); + final Configuration apiElements = project.getConfigurations().getByName("pluginApiElements"); + assertThat(apiElements.getOutgoing().getArtifacts(), emptyIterable()); + assertThat(apiElements.getOutgoing().getVariants(), emptyIterable()); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRuleIntegrationTests.java new file mode 100644 index 00000000..32800362 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRuleIntegrationTests.java @@ -0,0 +1,32 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.tasks.SourceSet; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .add("apiSourceSet", project.getObjects().property(SourceSet.class)); + } + + @Test + void disallowChangesOnApiSourceSetProperty() { + subject.execute(project); + assertThrows(IllegalStateException.class, + () -> apiSourceSet(gradlePlugin(project)).set((SourceSet) null)); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRuleIntegrationTests.java new file mode 100644 index 00000000..8b916b20 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRuleIntegrationTests.java @@ -0,0 +1,52 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.tasks.SourceSet; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.Before; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.capabilities; +import static dev.gradleplugins.ProjectMatchers.coordinate; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.java; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; + +class ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRuleIntegrationTests { + Project project = ProjectBuilder.builder().withName("foo").build(); + Action subject = new ApiSourceSet_PluginDependsOnApiSourceSetIfAvailableRule(); + + @BeforeEach + void configureProject() { + project.setGroup("com.example"); + project.setVersion("1.2"); + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .add("apiSourceSet", project.getObjects().property(SourceSet.class)); + gradlePlugin(project).pluginSourceSet(sourceSets(project).map(it -> it.maybeCreate("plugin")).get()); + java(project).registerFeature("plugin", spec -> spec.usingSourceSet(gradlePlugin(project).getPluginSourceSet())); + } + + @Test + void addsDependencyToApiArtifact() { + apiSourceSet(gradlePlugin(project)).set(sourceSets(project).map(it -> it.maybeCreate("myApi"))); + subject.execute(project); + assertThat(project.getConfigurations().getByName("pluginApi").getDependencies(), + hasItem(allOf(coordinate("com.example:foo:1.2"), capabilities(hasItem(coordinate("com.example:foo-api:1.2")))))); + } + + @Test + void doesNotAddDependencyToApiArtifactWhenNotPresent() { + subject.execute(project); + assertThat(project.getConfigurations().getByName("pluginApi").getDependencies(), + not(hasItem(allOf(coordinate("com.example:foo:1.2"), capabilities(hasItem(coordinate("com.example:foo-api:1.2"))))))); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRuleIntegrationTests.java new file mode 100644 index 00000000..24176bd4 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRuleIntegrationTests.java @@ -0,0 +1,47 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.plugins.ExtensionAware; +import org.gradle.api.tasks.SourceSet; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.named; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItems; + +class ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + ((ExtensionAware) gradlePlugin(project)).getExtensions() + .add("apiSourceSet", project.getObjects().property(SourceSet.class)); + } + + @Test + void registerApiFeatureWhenApiSourceSetAvailable() { + apiSourceSet(gradlePlugin(project)).set(sourceSets(project).map(it -> it.maybeCreate("myApi"))); + subject.execute(project); + + // These configurations only exists if a feature exists for the source set + assertThat(project.getConfigurations(), hasItems(named("myApiApi"), named("myApiApiElements"), named("myApiRuntimeElements"))); + } + + @Test + void doesNotRegisterApiFeatureWhenApiSourceSetAvailable() { + subject.execute(project); + + // Only the default outgoing variants exists + assertThat(project.getConfigurations().matching(it -> it.getName().endsWith("Elements")), + containsInAnyOrder(named("apiElements"), named("runtimeElements"))); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRuleIntegrationTests.java new file mode 100644 index 00000000..f95f9223 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRuleIntegrationTests.java @@ -0,0 +1,52 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.provider.Property; +import org.gradle.api.reflect.TypeOf; +import org.gradle.api.tasks.SourceSet; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static dev.gradleplugins.ProjectMatchers.absentProvider; +import static dev.gradleplugins.ProjectMatchers.extensions; +import static dev.gradleplugins.ProjectMatchers.named; +import static dev.gradleplugins.ProjectMatchers.publicType; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; +import static dev.gradleplugins.internal.util.SourceSetUtils.sourceSets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new ApiSourceSet_RegisterApiSourceSetPropertyOnGradlePluginDevelopmentExtensionRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + } + + @Test + void registersPropertyForApiSourceSetOnGradleDevelopmentExtension() { + subject.execute(project); + assertThat(gradlePlugin(project), extensions(hasItem(allOf( + named("apiSourceSet"), publicType(new TypeOf>() {}))))); + } + + @Test + void hasNoDefaultValue() { + subject.execute(project); + assertThat(apiSourceSet(gradlePlugin(project)), absentProvider()); + } + + @Test + void finalizeValueOnRead() { + subject.execute(project); + apiSourceSet(gradlePlugin(project)).value(sourceSets(project).map(it -> it.maybeCreate("my-api"))).get(); + assertThrows(IllegalStateException.class, () -> apiSourceSet(gradlePlugin(project)).set((SourceSet) null)); + } +} From 889e8259fbc7afb9ef722f7588b06cb653c90f5f Mon Sep 17 00:00:00 2001 From: Daniel Lacasse Date: Tue, 20 Sep 2022 12:30:58 -0400 Subject: [PATCH 19/19] Include dependency between versioned source set and API source set Signed-off-by: Daniel Lacasse --- .../GradlePluginDevelopmentBasePlugin.java | 2 ++ ..._DependsOnApiSourceSetIfAvailableRule.java | 30 +++++++++++++++++++ ...rceSetIfAvailableRuleIntegrationTests.java | 16 ++++++++++ 3 files changed, 48 insertions(+) create mode 100644 subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule.java create mode 100644 subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRuleIntegrationTests.java diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java index 6ac25515..2c37ee21 100644 --- a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/plugins/GradlePluginDevelopmentBasePlugin.java @@ -6,6 +6,7 @@ import dev.gradleplugins.internal.rules.VersionedSourceSet_AddVersionedComponentDependencyToPluginSourceSetAsImplementationDependencyRule; import dev.gradleplugins.internal.rules.ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule; import dev.gradleplugins.internal.rules.ConfigureMinimumGradleVersionConventionWithCurrentGradleVersionRule; +import dev.gradleplugins.internal.rules.VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule; import dev.gradleplugins.internal.rules.ApiSourceSet_RegisterApiSourceSetAsJavaFeatureWhenAvailableRule; import dev.gradleplugins.internal.rules.ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule; import dev.gradleplugins.internal.rules.FinalizeCompatibilityExtensionRule; @@ -36,6 +37,7 @@ public void apply(Project project) { new RemoveGradleApiSelfResolvingDependencyFromMainApiConfigurationRule().execute(project); new ConfigureGradleApiVersionConventionBasedOnMinimumGradleVersionRule().execute(project); new VersionedSourceSet_AddGradleApiDependencyToCompileOnlyConfigurationOfEachVersionedSourceSetRule().execute(project); + new VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule().execute(project); project.afterEvaluate(withoutParameter(() -> { new ApiSourceSet_LockApiSourceSetPropertyOnGradleExtensionPluginDevelopmentExtensionRule().execute(project); diff --git a/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule.java b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule.java new file mode 100644 index 00000000..240e0e13 --- /dev/null +++ b/subprojects/gradle-plugin-development/src/main/java/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule.java @@ -0,0 +1,30 @@ +package dev.gradleplugins.internal.rules; + +import dev.gradleplugins.internal.RuleGroup; +import dev.gradleplugins.internal.util.SourceSetUtils; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; + +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.apiClassifier; +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.asDependency; +import static dev.gradleplugins.internal.rules.VersionedSourceSetUtils.isVersionedSourceSet; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.matching; +import static dev.gradleplugins.internal.util.DomainObjectCollectionUtils.singleOrEmpty; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.apiSourceSet; +import static dev.gradleplugins.internal.util.GradlePluginDevelopmentUtils.gradlePlugin; + +@RuleGroup(VersionedSourceSetGroup.class) +public final class VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule implements Action { + @Override + public void execute(Project project) { + SourceSetUtils.sourceSets(project, it -> it.configureEach(matching(isVersionedSourceSet(), sourceSet -> { + project.getConfigurations().named(sourceSet.getImplementationConfigurationName(), configuration -> { + configuration.getDependencies().addAllLater(project.getObjects().setProperty(Dependency.class) + .value(singleOrEmpty(apiSourceSet(gradlePlugin(project)) + .map(__ -> apiClassifier()) + .map(asDependency(project))))); + }); + }))); + } +} diff --git a/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRuleIntegrationTests.java b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRuleIntegrationTests.java new file mode 100644 index 00000000..4ab5fc1a --- /dev/null +++ b/subprojects/gradle-plugin-development/src/test/groovy/dev/gradleplugins/internal/rules/VersionedSourceSet_DependsOnApiSourceSetIfAvailableRuleIntegrationTests.java @@ -0,0 +1,16 @@ +package dev.gradleplugins.internal.rules; + +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; + +class VersionedSourceSet_DependsOnApiSourceSetIfAvailableRuleIntegrationTests { + Project project = ProjectBuilder.builder().build(); + Action subject = new VersionedSourceSet_DependsOnApiSourceSetIfAvailableRule(); + + @BeforeEach + void configureProject() { + project.getPluginManager().apply("java-gradle-plugin"); + } +}