diff --git a/src/main/groovy/org/beryx/jlink/util/Util.groovy b/src/main/groovy/org/beryx/jlink/util/Util.groovy index 29c2fe7b..5e92fbd7 100644 --- a/src/main/groovy/org/beryx/jlink/util/Util.groovy +++ b/src/main/groovy/org/beryx/jlink/util/Util.groovy @@ -67,7 +67,11 @@ class Util { private static final String IMPORT_DECLARATION = 'import' + IGNORE + '(static' + IGNORE + ')?' + QUALIFIED_NAME + '(\\.\\*' + ')?' + IGNORE + ';' private static final String IMPORT_DECLARATIONS = '(' + IMPORT_DECLARATION + IGNORE + ')*' - private static final String MODULE_DECLARATION = '(?s)' + IGNORE + IMPORT_DECLARATIONS + '(open' + IGNORE + ')?' + 'module' + IGNORE + '(?' + QUALIFIED_NAME + ').*?' + + private static final String ANNOTATION = '(@' + IGNORE + QUALIFIED_NAME + '((' + IGNORE + ')(\\([^)]*\\)))?)' + private static final String MODULE_ANNOTATIONS = '(' + ANNOTATION + IGNORE + ')*' + + private static final String MODULE_DECLARATION = '(?s)' + IGNORE + IMPORT_DECLARATIONS + MODULE_ANNOTATIONS + '(open' + IGNORE + ')?' + 'module' + IGNORE + '(?' + QUALIFIED_NAME + ').*?' private static final Pattern PATTERN = Pattern.compile(MODULE_DECLARATION) diff --git a/src/test/groovy/org/beryx/jlink/JlinkPluginSpec.groovy b/src/test/groovy/org/beryx/jlink/JlinkPluginSpec.groovy index 29beba82..b230bfa1 100644 --- a/src/test/groovy/org/beryx/jlink/JlinkPluginSpec.groovy +++ b/src/test/groovy/org/beryx/jlink/JlinkPluginSpec.groovy @@ -205,6 +205,21 @@ class JlinkPluginSpec extends Specification { checkOutput(result, 'helloBom', '{"from":"Alice","to":"Bob","greeting":"Hello"}') } + def "should create runtime image of project with annotations on module declaration"() { + when: + File buildFile = setUpBuild('hello-annotated-module') + BuildResult result = GradleRunner.create() + .withDebug(true) + .withGradleVersion('7.6') + .withProjectDir(testProjectDir.toFile()) + .withPluginClasspath() + .withArguments(JlinkPlugin.TASK_NAME_JLINK, "-is") + .build(); + + then: + checkOutput(result, 'helloAnnotatedModule', 'Hello annotated module!') + } + def "should create image of project with multiple launchers"() { when: diff --git a/src/test/groovy/org/beryx/jlink/UtilSpec.groovy b/src/test/groovy/org/beryx/jlink/UtilSpec.groovy index 381de45b..94c43cb8 100644 --- a/src/test/groovy/org/beryx/jlink/UtilSpec.groovy +++ b/src/test/groovy/org/beryx/jlink/UtilSpec.groovy @@ -44,13 +44,17 @@ class UtilSpec extends Specification { Util.getModuleNameFrom(text) == moduleName where: - text | moduleName - 'module a.b.c\n{' | 'a.b.c' - 'open module a.b.c{}' | 'a.b.c' - ' \t open\t \tmodule \ta.b.c\t { ' | 'a.b.c' - '/*my module*/\nmodule /*---*/ a.b.c // declaration\n{\n exports a.b.c;\n}' | 'a.b.c' - 'import x.y.Z;//comment\nimport x.y.W;\nmodule /*---*/ a.b.c' | 'a.b.c' - 'import x.y.z.*;\nimport x.y/*WW*/./*ZZ*/w.*;\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' + text | moduleName + 'module a.b.c\n{' | 'a.b.c' + 'open module a.b.c{}' | 'a.b.c' + ' \t open\t \tmodule \ta.b.c\t { ' | 'a.b.c' + '/*my module*/\nmodule /*---*/ a.b.c // declaration\n{\n exports a.b.c;\n}' | 'a.b.c' + 'import x.y.Z;//comment\nimport x.y.W;\nmodule /*---*/ a.b.c' | 'a.b.c' + 'import x.y.z.*;\nimport x.y/*WW*/./*ZZ*/w.*;\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' + 'import x.y.z.*;\n@Annotation\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' + 'import x.y.z.*;\n@Annotation("text")\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' + 'import x.y.z.*;\n@ Annotation("text")\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' + 'import x.y.z.*;\n@Annotation\n(\n var = "text"\n)\nmodule //x.y.z\n/*-->*/a.b.c' | 'a.b.c' } @Unroll diff --git a/src/test/resources/hello-annotated-module/build.gradle b/src/test/resources/hello-annotated-module/build.gradle new file mode 100644 index 00000000..709e5e56 --- /dev/null +++ b/src/test/resources/hello-annotated-module/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'org.beryx.jlink' + id 'org.javamodularity.moduleplugin' version '1.8.12' +} + +repositories { + mavenCentral() +} + +sourceCompatibility = 17 +targetCompatibility = 17 + +dependencies { + implementation 'org.jspecify:jspecify:1.0.0' +} + +application { + mainClass = 'org.beryx.modular.annotatedmodule.HelloAnnotatedModule' +} +jar { + manifest { + attributes 'Implementation-Title': 'helloAnnotatedModule', + 'Main-Class': application.mainClass + } +} + +jlink { + launcher { + name = 'helloAnnotatedModule' + } +} diff --git a/src/test/resources/hello-annotated-module/settings.gradle b/src/test/resources/hello-annotated-module/settings.gradle new file mode 100644 index 00000000..f62081b6 --- /dev/null +++ b/src/test/resources/hello-annotated-module/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'helloAnnotatedModule' diff --git a/src/test/resources/hello-annotated-module/src/main/java/module-info.java b/src/test/resources/hello-annotated-module/src/main/java/module-info.java new file mode 100644 index 00000000..a253ac3f --- /dev/null +++ b/src/test/resources/hello-annotated-module/src/main/java/module-info.java @@ -0,0 +1,7 @@ +import org.jspecify.annotations.NullMarked; + +@NullMarked +module org.beryx.modular.annotatedmodule { + requires org.jspecify; + opens org.beryx.modular.annotatedmodule; +} diff --git a/src/test/resources/hello-annotated-module/src/main/java/org/beryx/modular/annotatedmodule/HelloAnnotatedModule.java b/src/test/resources/hello-annotated-module/src/main/java/org/beryx/modular/annotatedmodule/HelloAnnotatedModule.java new file mode 100644 index 00000000..2c6eb853 --- /dev/null +++ b/src/test/resources/hello-annotated-module/src/main/java/org/beryx/modular/annotatedmodule/HelloAnnotatedModule.java @@ -0,0 +1,9 @@ +package org.beryx.modular.annotatedmodule; + +import java.io.StringReader; + +public class HelloAnnotatedModule { + public static void main(String[] args) throws Exception { + System.out.println("Hello annotated module!"); + } +} diff --git a/src/test/resources/hello-toolchain/build.gradle b/src/test/resources/hello-toolchain/build.gradle index 7390eadf..2fdc7389 100644 --- a/src/test/resources/hello-toolchain/build.gradle +++ b/src/test/resources/hello-toolchain/build.gradle @@ -21,8 +21,8 @@ application { java { toolchain { - languageVersion = JavaLanguageVersion.of(23) - vendor = JvmVendorSpec.ADOPTIUM + languageVersion = JavaLanguageVersion.of(24) + //vendor = JvmVendorSpec.ADOPTIUM } }