From 4812f0ae3c5a47ba1a25d8faaa9cca3315342032 Mon Sep 17 00:00:00 2001 From: Big Andy <8012398+big-andy-coates@users.noreply.github.com> Date: Thu, 21 Jul 2022 16:20:52 +0100 Subject: [PATCH 1/3] Add failing test --- .../moduleplugin/ModulePluginSmokeTest.java | 14 +++-- test-project-kotlin-pre-1-7/README.md | 40 +++++++++++++ test-project-kotlin-pre-1-7/build.gradle.kts | 59 +++++++++++++++++++ test-project-kotlin-pre-1-7/gradle.properties | 2 + .../greeter.api/build.gradle.kts | 21 +++++++ .../src/main/java/module-info.java | 4 ++ .../kotlin/examples/greeter/api/Greeter.kt | 5 ++ .../greeter.javaexec/build.gradle.kts | 28 +++++++++ .../src/main/java/module-info.java | 8 +++ .../src/main/kotlin/demo/Demo1.kt | 12 ++++ .../src/main/kotlin/demo/Demo2.kt | 12 ++++ .../greeter.provider.test/build.gradle.kts | 13 ++++ .../src/main/java/module-info.java | 7 +++ .../src/main/kotlin/tests/GreeterLocator.kt | 13 ++++ .../src/test/kotlin/tests/GreeterTest.kt | 13 ++++ .../build.gradle.kts | 19 ++++++ .../src/main/java/module-info.java | 7 +++ .../main/kotlin/testfixture/GreeterLocator.kt | 13 ++++ .../test/kotlin/testfixture/GreeterTest.kt | 13 ++++ .../kotlin/testfixture/GreeterFixture.kt | 5 ++ .../greeter.provider/build.gradle.kts | 24 ++++++++ .../src/main/java/module-info.java | 7 +++ .../main/kotlin/examples/greeter/Friendly.kt | 12 ++++ .../src/main/resources/greeting.txt | 1 + .../kotlin/examples/greeter/FriendlyTest.kt | 12 ++++ .../kotlin/examples/greeter/ScriptingTest.kt | 14 +++++ .../src/test/kotlin/module-info.test | 7 +++ .../greeter.runner/build.gradle.kts | 36 +++++++++++ .../src/main/java/module-info.java | 7 +++ .../src/main/kotlin/examples/Runner.kt | 21 +++++++ .../src/main/resources/resourcetest.txt | 0 .../greeter.startscripts/build.gradle.kts | 48 +++++++++++++++ .../src/main/java/module-info.java | 8 +++ .../src/main/kotlin/startscripts/Demo1.kt | 5 ++ .../src/main/kotlin/startscripts/Demo2.kt | 5 ++ .../main/kotlin/startscripts/DemoHelper.kt | 16 +++++ .../src/main/kotlin/startscripts/MainDemo.kt | 5 ++ .../local_maven_settings.gradle | 16 +++++ test-project-kotlin-pre-1-7/settings.gradle | 16 +++++ .../smoke_test_settings.gradle | 11 ++++ test-project-kotlin/build.gradle.kts | 2 +- 41 files changed, 574 insertions(+), 7 deletions(-) create mode 100644 test-project-kotlin-pre-1-7/README.md create mode 100644 test-project-kotlin-pre-1-7/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/gradle.properties create mode 100644 test-project-kotlin-pre-1-7/greeter.api/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.api/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.api/src/main/kotlin/examples/greeter/api/Greeter.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.javaexec/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.javaexec/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo1.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo2.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.test/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.test/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.test/src/main/kotlin/tests/GreeterLocator.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.test/src/test/kotlin/tests/GreeterTest.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.testfixture/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/kotlin/testfixture/GreeterLocator.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/test/kotlin/testfixture/GreeterTest.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/testFixtures/kotlin/testfixture/GreeterFixture.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/main/resources/greeting.txt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/FriendlyTest.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/ScriptingTest.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/module-info.test create mode 100644 test-project-kotlin-pre-1-7/greeter.runner/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.runner/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.runner/src/main/kotlin/examples/Runner.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.runner/src/main/resources/resourcetest.txt create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/build.gradle.kts create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/src/main/java/module-info.java create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo1.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo2.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/DemoHelper.kt create mode 100644 test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/MainDemo.kt create mode 100644 test-project-kotlin-pre-1-7/local_maven_settings.gradle create mode 100644 test-project-kotlin-pre-1-7/settings.gradle create mode 100644 test-project-kotlin-pre-1-7/smoke_test_settings.gradle diff --git a/src/test/java/org/javamodularity/moduleplugin/ModulePluginSmokeTest.java b/src/test/java/org/javamodularity/moduleplugin/ModulePluginSmokeTest.java index 1307a49..cc430a2 100644 --- a/src/test/java/org/javamodularity/moduleplugin/ModulePluginSmokeTest.java +++ b/src/test/java/org/javamodularity/moduleplugin/ModulePluginSmokeTest.java @@ -37,7 +37,7 @@ void before() throws IOException { } @CartesianProductTest(name = "smokeTest({arguments})") - @CartesianValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"}) + @CartesianValueSource(strings = {"test-project", "test-project-kotlin-pre-1-7", "test-project-kotlin", "test-project-groovy"}) @CartesianValueSource(strings = {"5.1", "5.6", "6.3", "6.4.1", "6.5.1", "6.8.3", "7.0", "7.2"}) void smokeTest(String projectName, String gradleVersion) { LOGGER.lifecycle("Executing smokeTest of {} with Gradle {}", projectName, gradleVersion); @@ -60,7 +60,7 @@ void smokeTest(String projectName, String gradleVersion) { } @CartesianProductTest(name = "smokeTestRun({arguments})") - @CartesianValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"}) + @CartesianValueSource(strings = {"test-project", "test-project-kotlin-pre-1-7", "test-project-kotlin", "test-project-groovy"}) @CartesianValueSource(strings = {"5.1", "5.6", "6.3", "6.4.1", "6.5.1", "6.8.3", "7.0", "7.2"}) void smokeTestRun(String projectName, String gradleVersion) { LOGGER.lifecycle("Executing smokeTestRun of {} with Gradle {}", projectName, gradleVersion); @@ -158,7 +158,7 @@ private static void assertExpectedClassFileFormats( } @CartesianProductTest(name = "smokeTestDist({arguments})") - @CartesianValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"}) + @CartesianValueSource(strings = {"test-project", "test-project-kotlin-pre-1-7", "test-project-kotlin", "test-project-groovy"}) @CartesianValueSource(strings = {"5.1", "5.6", "6.3", "6.4.1", "6.5.1", "6.8.3", "7.0", "7.2"}) void smokeTestDist(String projectName, String gradleVersion) { LOGGER.lifecycle("Executing smokeTestDist of {} with Gradle {}", projectName, gradleVersion); @@ -199,7 +199,7 @@ void smokeTestDist(String projectName, String gradleVersion) { } @CartesianProductTest(name = "smokeTestRunDemo({arguments})") - @CartesianValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"}) + @CartesianValueSource(strings = {"test-project", "test-project-kotlin-pre-1-7", "test-project-kotlin", "test-project-groovy"}) @CartesianValueSource(strings = {"5.1", "5.6", "6.3", "6.4.1", "6.5.1", "6.8.3", "7.0", "7.2"}) void smokeTestRunDemo(String projectName, String gradleVersion) { LOGGER.lifecycle("Executing smokeTestRunDemo of {} with Gradle {}", projectName, gradleVersion); @@ -218,7 +218,7 @@ void smokeTestRunDemo(String projectName, String gradleVersion) { } @CartesianProductTest(name = "smokeTestRunStartScripts({arguments})") - @CartesianValueSource(strings = {"test-project", "test-project-kotlin", "test-project-groovy"}) + @CartesianValueSource(strings = {"test-project", "test-project-kotlin-pre-1-7", "test-project-kotlin", "test-project-groovy"}) @CartesianValueSource(strings = {"5.1", "5.6", "6.3", "6.4.1", "6.5.1", "6.8.3", "7.0", "7.2"}) void smokeTestRunStartScripts(String projectName, String gradleVersion) { LOGGER.lifecycle("Executing smokeTestRunScripts of {} with Gradle {}", projectName, gradleVersion); @@ -248,7 +248,9 @@ private static void assertTasksSuccessful(BuildResult result, String subprojectN } private static boolean checkCombination(String projectName, String gradleVersion) { - if(projectName.equals("test-project-kotlin") && gradleVersion.compareTo("6.4") < 0) { + final boolean kotlin_NotSupported = projectName.startsWith("test-project-kotlin") && gradleVersion.compareTo("6.4") < 0; + final boolean kotlin1_7_NotSupported = projectName.equals("test-project-kotlin") && gradleVersion.compareTo("6.6") < 0; + if (kotlin_NotSupported || kotlin1_7_NotSupported) { LOGGER.lifecycle("Unsupported combination: {} / Gradle {}. Test skipped", projectName, gradleVersion); return false; } diff --git a/test-project-kotlin-pre-1-7/README.md b/test-project-kotlin-pre-1-7/README.md new file mode 100644 index 0000000..58bcca6 --- /dev/null +++ b/test-project-kotlin-pre-1-7/README.md @@ -0,0 +1,40 @@ +Introduction +=== + +This Kotlin test project can be used as a standalone test project to verify the published plugin. +It is also used as an internal test project for testing unpublished plugin changes. + +Standalone test product +=== +To run this product as a standalone test product use this command (launched from `test-project-kotlin` directory): +``` +../gradlew clean build +``` + +It will use the most recent plugin version from Gradle maven repository to compile the test project with +modules and run the unit tests. + +Testing locally published plugin +=== + +You can publish the plugin locally by running this command from the root directory: + +`./gradlew publishToMavenLocal` + +You can test the locally published plugin by running the following command from `test-project-kotlin` directory. + +`../gradlew -c local_maven_settings.gradle clean build` + +It will use the locally published version of the plugin to compile the test project with +modules and run the unit tests. + + +Internal test project +=== + +This mode is enabled in `ModulePluginSmokeTest` by passing an extra parameter (`-c smoke_test_settings.gradle`). +`smoke_test_settings.gradle` script configures plugin management for `build.gradle.kts` so that the plugin cannot be resolved from +a Gradle plugin repository. Instead, it relies on the smoke test to make the plugin under development available +to the test project by sharing a classpath (using Gradle TestKit). + +__CAUTION:__ This approach won't work outside of the smoke test, it will break the build because the plugin jar won't be resolved. diff --git a/test-project-kotlin-pre-1-7/build.gradle.kts b/test-project-kotlin-pre-1-7/build.gradle.kts new file mode 100644 index 0000000..d4b0d84 --- /dev/null +++ b/test-project-kotlin-pre-1-7/build.gradle.kts @@ -0,0 +1,59 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") version "1.3.72" apply false + id("org.javamodularity.moduleplugin") version "1.8.11" apply false +} + +subprojects { + apply(plugin = "kotlin") + apply(plugin = "org.javamodularity.moduleplugin") + + //region https://docs.gradle.org/current/userguide/kotlin_dsl.html#using_kotlin_delegated_properties + val test by tasks.existing(Test::class) + val build by tasks + val javadoc by tasks + + val implementation by configurations + val testImplementation by configurations + val testRuntimeOnly by configurations + + val jUnitVersion: String by project + val jUnitPlatformVersion: String by project + //endregion + + //region KOTLIN + tasks.withType { + kotlinOptions.jvmTarget = "1.8" + } + dependencies { + implementation(kotlin("stdlib-jdk8")) + } + //endregion + + repositories { + mavenCentral() + } + + configure { + improveEclipseClasspathFile() + moduleVersion("1.2.3") + } + + test { + useJUnitPlatform() + + testLogging { + events("PASSED", "FAILED", "SKIPPED", "STANDARD_OUT") + } + } + + dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:$jUnitVersion") + testImplementation("org.junit.jupiter:junit-jupiter-params:$jUnitVersion") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jUnitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:$jUnitPlatformVersion") + } + +// build.dependsOn(javadoc) // TODO: No public or protected classes found to document +} diff --git a/test-project-kotlin-pre-1-7/gradle.properties b/test-project-kotlin-pre-1-7/gradle.properties new file mode 100644 index 0000000..5ef2ebc --- /dev/null +++ b/test-project-kotlin-pre-1-7/gradle.properties @@ -0,0 +1,2 @@ +jUnitVersion = 5.6.2 +jUnitPlatformVersion = 1.6.2 diff --git a/test-project-kotlin-pre-1-7/greeter.api/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.api/build.gradle.kts new file mode 100644 index 0000000..1b1e61f --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.api/build.gradle.kts @@ -0,0 +1,21 @@ +import org.javamodularity.moduleplugin.extensions.CompileModuleOptions +import org.javamodularity.moduleplugin.extensions.TestModuleOptions + +//region NO-OP (DSL testing) +tasks.compileJava { + extensions.configure { + addModules = listOf() + compileModuleInfoSeparately = false + } +} + +tasks.test { + extensions.configure { + addModules = listOf() + runOnClasspath = false + } +} + +modularity { +} +//endregion diff --git a/test-project-kotlin-pre-1-7/greeter.api/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.api/src/main/java/module-info.java new file mode 100644 index 0000000..3668393 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.api/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module greeter.api { + exports examples.greeter.api; + requires kotlin.stdlib; +} diff --git a/test-project-kotlin-pre-1-7/greeter.api/src/main/kotlin/examples/greeter/api/Greeter.kt b/test-project-kotlin-pre-1-7/greeter.api/src/main/kotlin/examples/greeter/api/Greeter.kt new file mode 100644 index 0000000..b3c479e --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.api/src/main/kotlin/examples/greeter/api/Greeter.kt @@ -0,0 +1,5 @@ +package examples.greeter.api + +interface Greeter { + fun hello(): String +} diff --git a/test-project-kotlin-pre-1-7/greeter.javaexec/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.javaexec/build.gradle.kts new file mode 100644 index 0000000..f193b76 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.javaexec/build.gradle.kts @@ -0,0 +1,28 @@ +import org.javamodularity.moduleplugin.tasks.ModularJavaExec + +val moduleName: String by project + +dependencies { + implementation(project(":greeter.api")) + runtimeOnly(project(":greeter.provider")) +} + +patchModules.config = listOf( + "java.annotation=jsr305-3.0.2.jar" +) +modularity { + patchModule("java.annotation", "jsr250-api-1.0.jar") +} + +File("${project.projectDir}/src/main/kotlin/demo") + .listFiles({ _, name -> Regex("Demo.*\\.kt") matches name }) + .forEach { file -> + val demoClassName = file.name.removeSuffix(".kt") + tasks.create("run$demoClassName") { + group = "Demo" + description = "Run the $demoClassName program" + mainClass.set("demo.${demoClassName}Kt") + mainModule.set(moduleName) + jvmArgs = listOf("-Xmx128m") + } + } diff --git a/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/java/module-info.java new file mode 100644 index 0000000..c5f2162 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/java/module-info.java @@ -0,0 +1,8 @@ +import examples.greeter.api.Greeter; + +module greeter.javaexec { + requires greeter.api; + requires kotlin.stdlib; + + uses Greeter; +} diff --git a/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo1.kt b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo1.kt new file mode 100644 index 0000000..a94be04 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo1.kt @@ -0,0 +1,12 @@ +package demo + +import examples.greeter.api.Greeter + +import java.util.ServiceLoader + +fun main(args: Array) { + val greeter = ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow{RuntimeException("No Greeter found!")} + println("Demo1: " + greeter.hello()) +} diff --git a/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo2.kt b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo2.kt new file mode 100644 index 0000000..1b3865b --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.javaexec/src/main/kotlin/demo/Demo2.kt @@ -0,0 +1,12 @@ +package demo + +import examples.greeter.api.Greeter + +import java.util.ServiceLoader + +fun main(args: Array) { + val greeter = ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow { RuntimeException("No Greeter found!") } + println("Demo2: " + greeter.hello()) +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.test/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.provider.test/build.gradle.kts new file mode 100644 index 0000000..8a82ac1 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.test/build.gradle.kts @@ -0,0 +1,13 @@ +dependencies { + implementation(project(":greeter.api")) + runtimeOnly(project(":greeter.provider")) +} + +modularity { + patchModule("java.annotation", "jsr305-3.0.2.jar") + patchModule("java.annotation", "jsr250-api-1.0.jar") +} + +val compileTestJava: JavaCompile by tasks.named("compileTestJava") +val moduleOptions: org.javamodularity.moduleplugin.extensions.ModuleOptions by compileTestJava.extensions +moduleOptions.addModules = listOf("jdk.unsupported") diff --git a/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/java/module-info.java new file mode 100644 index 0000000..35af0fc --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/java/module-info.java @@ -0,0 +1,7 @@ +import examples.greeter.api.Greeter; + +module greeter.provider.test { + requires greeter.api; + requires kotlin.stdlib; + uses Greeter; +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/kotlin/tests/GreeterLocator.kt b/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/kotlin/tests/GreeterLocator.kt new file mode 100644 index 0000000..ad4ec65 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.test/src/main/kotlin/tests/GreeterLocator.kt @@ -0,0 +1,13 @@ +package tests + +import examples.greeter.api.Greeter + +import java.util.ServiceLoader + +class GreeterLocator { + fun findGreeter(): Greeter { + return ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow{RuntimeException("No Greeter found")} + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.test/src/test/kotlin/tests/GreeterTest.kt b/test-project-kotlin-pre-1-7/greeter.provider.test/src/test/kotlin/tests/GreeterTest.kt new file mode 100644 index 0000000..22ceefa --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.test/src/test/kotlin/tests/GreeterTest.kt @@ -0,0 +1,13 @@ +package tests + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.assertFalse + +class GreeterTest { + @Test + fun testLocate() { + val greeter = GreeterLocator().findGreeter() + assertFalse(greeter.hello().isBlank()) + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.testfixture/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/build.gradle.kts new file mode 100644 index 0000000..e77802d --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + `java-test-fixtures` +} + +//// Include the main sourceset as a dependency of testFixtures. +//kotlin.target.compilations.getByName("testFixtures") { +// associateWith(target.compilations.getByName("main")) +//} + +dependencies { + implementation(project(":greeter.api")) + testFixturesImplementation(project(":greeter.api")) + runtimeOnly(project(":greeter.provider")) +} + +modularity { + patchModule("java.annotation", "jsr305-3.0.2.jar") + patchModule("java.annotation", "jsr250-api-1.0.jar") +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/java/module-info.java new file mode 100644 index 0000000..64302f6 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/java/module-info.java @@ -0,0 +1,7 @@ +import examples.greeter.api.Greeter; + +module greeter.provider.testfixture { + requires greeter.api; + requires kotlin.stdlib; + uses Greeter; +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/kotlin/testfixture/GreeterLocator.kt b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/kotlin/testfixture/GreeterLocator.kt new file mode 100644 index 0000000..b82f6b5 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/main/kotlin/testfixture/GreeterLocator.kt @@ -0,0 +1,13 @@ +package testfixture + +import examples.greeter.api.Greeter + +import java.util.ServiceLoader + +class GreeterLocator { + fun findGreeter(): Greeter { + return ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow{RuntimeException("No Greeter found")} + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/test/kotlin/testfixture/GreeterTest.kt b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/test/kotlin/testfixture/GreeterTest.kt new file mode 100644 index 0000000..2a5808d --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/test/kotlin/testfixture/GreeterTest.kt @@ -0,0 +1,13 @@ +package testfixture + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.assertFalse + +class GreeterTest: GreeterFixture() { + @Test + fun testLocate() { + val greeter = locator().findGreeter() + assertFalse(greeter.hello().isBlank()) + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/testFixtures/kotlin/testfixture/GreeterFixture.kt b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/testFixtures/kotlin/testfixture/GreeterFixture.kt new file mode 100644 index 0000000..5aa87b7 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider.testfixture/src/testFixtures/kotlin/testfixture/GreeterFixture.kt @@ -0,0 +1,5 @@ +package testfixture + +open class GreeterFixture { + fun locator() = GreeterLocator() +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.provider/build.gradle.kts new file mode 100644 index 0000000..2c2795e --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/build.gradle.kts @@ -0,0 +1,24 @@ +import org.javamodularity.moduleplugin.extensions.JavadocModuleOptions + +dependencies { + implementation(project(":greeter.api")) + implementation("javax.annotation:javax.annotation-api:1.3.2") + implementation("com.google.code.findbugs:jsr305:3.0.2") + implementation("javax.annotation:jsr250-api:1.0") + + testImplementation("org.hamcrest:hamcrest:2.1+") +} + +patchModules.config = listOf( + "java.annotation=jsr305-3.0.2.jar" +) + +modularity { + patchModule("java.annotation", "jsr250-api-1.0.jar") +} + +tasks.javadoc { + extensions.configure { + addModules = listOf("java.sql") + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.provider/src/main/java/module-info.java new file mode 100644 index 0000000..e89428a --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/main/java/module-info.java @@ -0,0 +1,7 @@ +import examples.greeter.api.Greeter; + +module greeter.provider { + requires greeter.api; + requires kotlin.stdlib; + provides Greeter with examples.greeter.Friendly; +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt b/test-project-kotlin-pre-1-7/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt new file mode 100644 index 0000000..0195604 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt @@ -0,0 +1,12 @@ +package examples.greeter + +import examples.greeter.api.Greeter +import java.io.* + +class Friendly: Greeter { + override fun hello(): String { + val stream = javaClass.getResourceAsStream("/greeting.txt") + val reader = BufferedReader(InputStreamReader(stream, "utf-8")) + return reader.readLine() + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/main/resources/greeting.txt b/test-project-kotlin-pre-1-7/greeter.provider/src/main/resources/greeting.txt new file mode 100644 index 0000000..b6cbc2d --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/main/resources/greeting.txt @@ -0,0 +1 @@ +welcome \ No newline at end of file diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/FriendlyTest.kt b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/FriendlyTest.kt new file mode 100644 index 0000000..25a8faf --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/FriendlyTest.kt @@ -0,0 +1,12 @@ +package examples.greeter + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.* + +class FriendlyTest { + @Test + fun testGreeting() { + val greeting = Friendly().hello() + assertTrue(greeting.contains("welcome")) + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/ScriptingTest.kt b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/ScriptingTest.kt new file mode 100644 index 0000000..5d8d127 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/examples/greeter/ScriptingTest.kt @@ -0,0 +1,14 @@ +package examples.greeter + +import javax.script.* +import org.junit.jupiter.api.* +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.* + +class ScriptingTest { + @Test + fun testScripting() { + val manager = ScriptEngineManager() + assertThat(manager.getEngineFactories(), not(nullValue())) + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/module-info.test b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/module-info.test new file mode 100644 index 0000000..4aa1e83 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.provider/src/test/kotlin/module-info.test @@ -0,0 +1,7 @@ +// make module visible +--add-modules + java.scripting,org.hamcrest + +// "requires java.scripting" +--add-reads + greeter.provider=java.scripting,org.hamcrest diff --git a/test-project-kotlin-pre-1-7/greeter.runner/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.runner/build.gradle.kts new file mode 100644 index 0000000..53c00fa --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.runner/build.gradle.kts @@ -0,0 +1,36 @@ +import org.javamodularity.moduleplugin.extensions.RunModuleOptions + +plugins { + application +} + +//region https://docs.gradle.org/current/userguide/kotlin_dsl.html#using_kotlin_delegated_properties +val moduleName: String by project +val run by tasks.existing(JavaExec::class) // https://youtrack.jetbrains.com/issue/KT-28013 +//endregion + +dependencies { + implementation(project(":greeter.api")) + runtimeOnly(project(":greeter.provider")) +} + +application { + mainClass.set("examples.RunnerKt") + mainModule.set(moduleName) + applicationDefaultJvmArgs = listOf("-Dgreeter.sender=gradle-modules-plugin") +} + +modularity { + patchModule("java.annotation", "jsr305-3.0.2.jar") +} +patchModules.config = listOf( + "java.annotation=jsr250-api-1.0.jar" +) + +(run) { + extensions.configure { + addModules = listOf("java.sql") + } + + jvmArgs = listOf("-Dgreeter.sender=gradle-modules-plugin") +} diff --git a/test-project-kotlin-pre-1-7/greeter.runner/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.runner/src/main/java/module-info.java new file mode 100644 index 0000000..8151796 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.runner/src/main/java/module-info.java @@ -0,0 +1,7 @@ +import examples.greeter.api.Greeter; + +module greeter.runner { + requires greeter.api; + requires kotlin.stdlib; + uses Greeter; +} diff --git a/test-project-kotlin-pre-1-7/greeter.runner/src/main/kotlin/examples/Runner.kt b/test-project-kotlin-pre-1-7/greeter.runner/src/main/kotlin/examples/Runner.kt new file mode 100644 index 0000000..03491ee --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.runner/src/main/kotlin/examples/Runner.kt @@ -0,0 +1,21 @@ +package examples + +import examples.greeter.api.Greeter + +import java.util.ServiceLoader + +fun main(args: Array) { + println("args: " + java.util.Arrays.asList(*args)) + println("greeter.sender: " + System.getProperty("greeter.sender")) + val greeter = ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow{RuntimeException("No Greeter found!")} + println(greeter.hello()) + + val resource = object: Any() {}.javaClass.getResourceAsStream("/resourcetest.txt") + if(resource == null) { + throw RuntimeException("Couldn't load resource") + } + ModuleLayer.boot().modules().map(Module::getName) + .find{it == "java.sql"} ?: throw RuntimeException("Expected module java.sql not found") +} diff --git a/test-project-kotlin-pre-1-7/greeter.runner/src/main/resources/resourcetest.txt b/test-project-kotlin-pre-1-7/greeter.runner/src/main/resources/resourcetest.txt new file mode 100644 index 0000000..e69de29 diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/build.gradle.kts b/test-project-kotlin-pre-1-7/greeter.startscripts/build.gradle.kts new file mode 100644 index 0000000..14187b2 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/build.gradle.kts @@ -0,0 +1,48 @@ +import org.javamodularity.moduleplugin.tasks.ModularCreateStartScripts +import org.javamodularity.moduleplugin.tasks.ModularJavaExec + +plugins { + application +} + +//region https://docs.gradle.org/current/userguide/kotlin_dsl.html#using_kotlin_delegated_properties +val moduleName: String by project +val installDist by tasks +//endregion + +dependencies { + implementation(project(":greeter.api")) + runtimeOnly(project(":greeter.provider")) +} + +modularity { + patchModule("java.annotation", "jsr250-api-1.0.jar") + patchModule("java.annotation", "jsr305-3.0.2.jar") +} + +application { + mainClass.set("startscripts.MainDemoKt") + mainModule.set(moduleName) + applicationName = "demo" + applicationDefaultJvmArgs = listOf("-Xmx128m") +} + +File("${project.projectDir}/src/main/kotlin/startscripts") + .listFiles({ _, name -> Regex("Demo.*\\.kt") matches name }) + .forEach { file -> + val demoClassName = file.name.removeSuffix(".kt") + + val runDemo = tasks.create("run$demoClassName") { + group = "Demo" + description = "Run the $demoClassName program" + main = "$moduleName/startscripts.${demoClassName}Kt" + jvmArgs = listOf("-Xmx128m") + } + + val createScripts = tasks.create("createStartScripts$demoClassName") { + runTask = runDemo + applicationName = demoClassName.decapitalize() + } + + installDist.finalizedBy(createScripts) + } diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/java/module-info.java b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/java/module-info.java new file mode 100644 index 0000000..8df89e5 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/java/module-info.java @@ -0,0 +1,8 @@ +import examples.greeter.api.Greeter; + +module greeter.startscripts { + requires greeter.api; + requires kotlin.stdlib; + + uses Greeter; +} diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo1.kt b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo1.kt new file mode 100644 index 0000000..34f7830 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo1.kt @@ -0,0 +1,5 @@ +package startscripts + +fun main(args: Array) { + DemoHelper.greet("Demo1", args) +} diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo2.kt b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo2.kt new file mode 100644 index 0000000..5bf75bc --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/Demo2.kt @@ -0,0 +1,5 @@ +package startscripts + +fun main(args: Array) { + DemoHelper.greet("Demo2", args) +} diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/DemoHelper.kt b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/DemoHelper.kt new file mode 100644 index 0000000..dc34d34 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/DemoHelper.kt @@ -0,0 +1,16 @@ +package startscripts + +import examples.greeter.api.Greeter +import java.util.ServiceLoader + +object DemoHelper { + fun greet(appName: String, args: Array) { + val greeter = ServiceLoader.load(Greeter::class.java) + .findFirst() + .orElseThrow{RuntimeException("No Greeter found!")} + val addition = System.getProperty("greeting.addition", "").let { + if(it.isBlank()) "" else " $it" + } + println("$appName: ${greeter.hello()}$addition" + args.joinToString(" and ", ", ", "!")) + } +} diff --git a/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/MainDemo.kt b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/MainDemo.kt new file mode 100644 index 0000000..a8f5af3 --- /dev/null +++ b/test-project-kotlin-pre-1-7/greeter.startscripts/src/main/kotlin/startscripts/MainDemo.kt @@ -0,0 +1,5 @@ +package startscripts + +fun main(args: Array) { + DemoHelper.greet("MainDemo", args) +} diff --git a/test-project-kotlin-pre-1-7/local_maven_settings.gradle b/test-project-kotlin-pre-1-7/local_maven_settings.gradle new file mode 100644 index 0000000..559bf61 --- /dev/null +++ b/test-project-kotlin-pre-1-7/local_maven_settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroup 'org.javamodularity.moduleplugin' // by 'publishToMavenLocal' task + } + } + mavenCentral { + content { + includeGroup 'com.github.javaparser' + } + } + } +} + +apply from: 'settings.gradle' diff --git a/test-project-kotlin-pre-1-7/settings.gradle b/test-project-kotlin-pre-1-7/settings.gradle new file mode 100644 index 0000000..d6987f7 --- /dev/null +++ b/test-project-kotlin-pre-1-7/settings.gradle @@ -0,0 +1,16 @@ +import org.gradle.util.GradleVersion + +rootProject.name = 'test-project-kotlin-pre-1-7' + +include 'greeter.api' + +include 'greeter.provider' +include 'greeter.provider.test' + +if(GradleVersion.current().compareTo(GradleVersion.version("5.6")) >= 0) { + include 'greeter.provider.testfixture' +} + +include 'greeter.runner' +include 'greeter.javaexec' +include 'greeter.startscripts' diff --git a/test-project-kotlin-pre-1-7/smoke_test_settings.gradle b/test-project-kotlin-pre-1-7/smoke_test_settings.gradle new file mode 100644 index 0000000..3efe266 --- /dev/null +++ b/test-project-kotlin-pre-1-7/smoke_test_settings.gradle @@ -0,0 +1,11 @@ +pluginManagement { + repositories { + gradlePluginPortal().with { + content { + excludeGroup 'org.javamodularity.moduleplugin' // added to the classpath by the smoke test + } + } + } +} + +apply from: 'settings.gradle' diff --git a/test-project-kotlin/build.gradle.kts b/test-project-kotlin/build.gradle.kts index d4b0d84..1b1b7e6 100644 --- a/test-project-kotlin/build.gradle.kts +++ b/test-project-kotlin/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.3.72" apply false + kotlin("jvm") version "1.7.10" apply false id("org.javamodularity.moduleplugin") version "1.8.11" apply false } From e9ffc69d541ca9ea8b20c1b488f0aa2be5f1a686 Mon Sep 17 00:00:00 2001 From: Big Andy <8012398+big-andy-coates@users.noreply.github.com> Date: Fri, 22 Jul 2022 10:23:28 +0100 Subject: [PATCH 2/3] Fix for Kotlin 1.7 breaking changes fixes: https://github.com/java9-modularity/gradle-modules-plugin/issues/212 The gradle plugin for Kotlin 1.7 included breaking changes, including making `KotlinCompile` no longer derive from `AbstractCompile`, breaking this plugin. (See https://kotlinlang.org/docs/whatsnew17.html#changes-in-compile-tasks). The fix is to factor out the information required from compile tasks into a `CompileTaskWrapper` interface and provide different impls for tasks derived from `AbstractCompile` vs those that are not (like `KotlinCompile`). The latter uses reflection to access the needed methods. --- .../tasks/CompileJavaTaskMutator.java | 4 +- .../tasks/MergeClassesHelper.java | 122 ++++++++++++++++-- .../moduleplugin/tasks/MergeClassesTask.java | 10 +- 3 files changed, 121 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/javamodularity/moduleplugin/tasks/CompileJavaTaskMutator.java b/src/main/java/org/javamodularity/moduleplugin/tasks/CompileJavaTaskMutator.java index f634960..3256b9d 100644 --- a/src/main/java/org/javamodularity/moduleplugin/tasks/CompileJavaTaskMutator.java +++ b/src/main/java/org/javamodularity/moduleplugin/tasks/CompileJavaTaskMutator.java @@ -4,12 +4,12 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; -import org.gradle.api.tasks.compile.AbstractCompile; import org.gradle.api.tasks.compile.JavaCompile; import org.javamodularity.moduleplugin.JavaProjectHelper; import org.javamodularity.moduleplugin.extensions.CompileModuleOptions; import org.javamodularity.moduleplugin.extensions.PatchModuleContainer; import org.javamodularity.moduleplugin.internal.MutatorHelper; +import org.javamodularity.moduleplugin.tasks.MergeClassesHelper.CompileTaskWrapper; import java.util.ArrayList; import java.util.List; @@ -60,7 +60,7 @@ private List buildCompilerArgs(JavaCompile javaCompile) { helper().modularityExtension().optionContainer().getPatchModuleContainer()); String moduleName = helper().moduleName(); new MergeClassesHelper(project).otherCompileTaskStream() - .map(AbstractCompile::getDestinationDir) + .map(CompileTaskWrapper::getDestinationDir) .forEach(dir -> patchModuleContainer.addDir(moduleName, dir.getAbsolutePath())); // Keep only valid module-path entries (https://github.com/java9-modularity/gradle-modules-plugin/issues/190) diff --git a/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesHelper.java b/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesHelper.java index 12e6f7c..d87cc6f 100644 --- a/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesHelper.java +++ b/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesHelper.java @@ -1,6 +1,8 @@ package org.javamodularity.moduleplugin.tasks; import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.DuplicatesStrategy; import org.gradle.api.file.FileCollection; import org.gradle.api.logging.Logger; @@ -15,10 +17,13 @@ import org.javamodularity.moduleplugin.internal.StreamHelper; import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Stream; public class MergeClassesHelper { @@ -38,10 +43,11 @@ public Project project() { return project; } - public Stream otherCompileTaskStream() { + public Stream otherCompileTaskStream() { return otherCompileTaskNameStream() - .map(name -> helper().findTask(name, AbstractCompile.class)) - .flatMap(Optional::stream); + .map(name -> helper().findTask(name, Task.class)) + .flatMap(Optional::stream) + .map(this::toWrapper); } private Stream otherCompileTaskNameStream() { @@ -52,16 +58,16 @@ private Stream otherCompileTaskNameStream() { ); } - public JavaCompile javaCompileTask() { - return helper().task(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile.class); + private CompileTaskWrapper javaCompileTask() { + return toWrapper(helper().task(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile.class)); } - public Stream allCompileTaskStream() { + public Stream allCompileTaskStream() { return Stream.concat(Stream.of(javaCompileTask()), otherCompileTaskStream()); } public boolean isMergeRequired() { - return otherCompileTaskStream().anyMatch(task -> !task.getSource().isEmpty()); + return otherCompileTaskStream().anyMatch(CompileTaskWrapper::hasSource); } public Sync createMergeClassesTask() { @@ -84,12 +90,112 @@ public FileCollection getMergeAdjustedClasspath(FileCollection classpath) { } Set files = new HashSet<>(classpath.getFiles()); - allCompileTaskStream().map(AbstractCompile::getDestinationDir).forEach(files::remove); + allCompileTaskStream().map(CompileTaskWrapper::getDestinationDir).forEach(files::remove); files.add(helper().getMergedDir()); return project.files(files.toArray()); } + private CompileTaskWrapper toWrapper(Task task) { + return task instanceof AbstractCompile + ? new GradleTaskWrapper((AbstractCompile) task) + : new ReflectionTaskWrapper(task); + } + private JavaProjectHelper helper() { return new JavaProjectHelper(project); } + + public interface CompileTaskWrapper { + Task getTask(); + + File getDestinationDir(); + + boolean hasSource(); + } + + private static final class GradleTaskWrapper implements CompileTaskWrapper { + + private final AbstractCompile task; + + GradleTaskWrapper(AbstractCompile task) { + this.task = task; + } + + @Override + public Task getTask() { + return task; + } + + @Override + public File getDestinationDir() { + return task.getDestinationDir(); + } + + @Override + public boolean hasSource() { + return !task.getSource().isEmpty(); + } + } + + private static final class ReflectionTaskWrapper implements CompileTaskWrapper { + + private final Task task; + private final Supplier destinationDir; + private final Supplier source; + + ReflectionTaskWrapper(Task task) { + this.task = task; + this.destinationDir = supplier( + task, + "getDestinationDirectory", + DirectoryProperty.class + ); + this.source = supplier( + task, + "getSources", + FileCollection.class + ); + } + + @Override + public Task getTask() { + return task; + } + + @Override + public File getDestinationDir() { + return destinationDir.get().getAsFile().getOrNull(); + } + + @Override + public boolean hasSource() { + return !source.get().isEmpty(); + } + + private static Supplier supplier(Task task, String getterName, Class getterReturnType) { + final Method m = getMethod(task, getterName); + + return () -> { + try { + final Object result = m.invoke(task); + return getterReturnType.cast(result); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof RuntimeException) { + throw (RuntimeException) e.getTargetException(); + } + throw new RuntimeException(e.getTargetException()); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to invoke " + getterName + " on " + task.getClass(), e); + } + }; + } + + private static Method getMethod(Task task, String name) { + try { + return task.getClass().getMethod(name); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Method " + name + " missing on " + task.getClass(), e); + } + } + } } diff --git a/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesTask.java b/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesTask.java index bb95a17..b4ff12f 100644 --- a/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesTask.java +++ b/src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesTask.java @@ -26,14 +26,14 @@ public void configureMergeClasses() { public void configureMergeClassesAfterEvaluate() { var mergeClasses = mergeClassesHelper().createMergeClassesTask(); - mergeClassesHelper().allCompileTaskStream().forEach(task -> { + mergeClassesHelper().allCompileTaskStream().forEach(taskWrapper -> { List modularTasks = List.of(JavaPlugin.COMPILE_JAVA_TASK_NAME, CompileModuleOptions.COMPILE_MODULE_INFO_TASK_NAME); - if(modularTasks.contains(task.getName())) { - mergeClasses.from(task.getDestinationDir()); + if(modularTasks.contains(taskWrapper.getTask().getName())) { + mergeClasses.from(taskWrapper.getDestinationDir()); } else { - mergeClasses.from(task.getDestinationDir(), copySpec -> copySpec.exclude("**/module-info.class")); + mergeClasses.from(taskWrapper.getDestinationDir(), copySpec -> copySpec.exclude("**/module-info.class")); } - mergeClasses.dependsOn(task); + mergeClasses.dependsOn(taskWrapper.getTask()); }); mergeClasses.into(helper().getMergedDir()); mergeClasses.onlyIf(task -> mergeClassesHelper().isMergeRequired()); From f5101fc89888064bf94c71e4ecfc2e86cd129a8a Mon Sep 17 00:00:00 2001 From: Big Andy <8012398+big-andy-coates@users.noreply.github.com> Date: Fri, 22 Jul 2022 22:22:29 +0100 Subject: [PATCH 3/3] Fix for broken test. Issue was that nothing was actually using the `javax.annotation` module in the project, i.e. a bug in the test project. For some reason updating the Kotlin jars caused the issue to be displayed. Fixed by having a module depend on the module. Also added a use of one of the types from one of the patched jars to ensure it working. --- .../greeter.provider/src/main/java/module-info.java | 1 + .../src/main/kotlin/examples/greeter/Friendly.kt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test-project-kotlin/greeter.provider/src/main/java/module-info.java b/test-project-kotlin/greeter.provider/src/main/java/module-info.java index e89428a..8303b0e 100644 --- a/test-project-kotlin/greeter.provider/src/main/java/module-info.java +++ b/test-project-kotlin/greeter.provider/src/main/java/module-info.java @@ -3,5 +3,6 @@ module greeter.provider { requires greeter.api; requires kotlin.stdlib; + requires java.annotation; provides Greeter with examples.greeter.Friendly; } diff --git a/test-project-kotlin/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt b/test-project-kotlin/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt index 0195604..72d1b6c 100644 --- a/test-project-kotlin/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt +++ b/test-project-kotlin/greeter.provider/src/main/kotlin/examples/greeter/Friendly.kt @@ -2,7 +2,9 @@ package examples.greeter import examples.greeter.api.Greeter import java.io.* +import javax.annotation.concurrent.Immutable; +@Immutable class Friendly: Greeter { override fun hello(): String { val stream = javaClass.getResourceAsStream("/greeting.txt")