+ * See details about the {@code --release} option + * here. + * + * @param mainJavaRelease value for the {@code --release} option of {@code compileJava} task (allowed range: 9+) + */ + void standardJavaRelease(int mainJavaRelease); + + /** + * Calling this method results in all Java classes being compiled to Java release 6-8 (as given by the + * {@code mainJavaRelease} parameter), with the exception of {@code module-info.java} being compiled to + * Java release 9. + * + * @param mainJavaRelease value for the {@code --release} option of {@code compileJava} task (allowed range: 6-8) + */ + default void mixedJavaRelease(int mainJavaRelease) { + mixedJavaRelease(mainJavaRelease, 9); + } + + /** + * Calling this method results in all Java classes being compiled to Java release 6-8 (as given by the + * {@code mainJavaRelease} parameter), with the exception of {@code module-info.java} being compiled to + * Java release 9+ (as given by the {@code moduleInfoJavaRelease} parameter). + *
+ * See details about the {@code --release} option
+ * here.
+ *
+ * @param mainJavaRelease value for the {@code --release} option of {@code compileJava} task
+ * (allowed range: 6-8)
+ * @param moduleInfoJavaRelease value for the {@code --release} option of {@code compileModuleInfoJava} task
+ * (allowed range: 9+)
+ */
+ void mixedJavaRelease(int mainJavaRelease, int moduleInfoJavaRelease);
+ //endregion
+}
diff --git a/src/main/java/org/javamodularity/moduleplugin/extensions/ModularityExtensionImpl.java b/src/main/java/org/javamodularity/moduleplugin/extensions/ModularityExtensionImpl.java
new file mode 100644
index 0000000..967ac82
--- /dev/null
+++ b/src/main/java/org/javamodularity/moduleplugin/extensions/ModularityExtensionImpl.java
@@ -0,0 +1,97 @@
+package org.javamodularity.moduleplugin.extensions;
+
+import org.gradle.api.JavaVersion;
+import org.gradle.api.Project;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.compile.JavaCompile;
+import org.javamodularity.moduleplugin.JavaProjectHelper;
+
+import java.util.List;
+
+public class ModularityExtensionImpl implements ModularityExtension {
+
+ private final Project project;
+
+ public ModularityExtensionImpl(Project project) {
+ this.project = project;
+ }
+
+ //region JAVA RELEASE
+
+ //region STANDARD JAVA RELEASE
+ @Override
+ public void standardJavaRelease(int mainJavaRelease) {
+ if (mainJavaRelease < 9) {
+ throw new IllegalArgumentException(String.format(
+ "Invalid main --release value: %d. Use 'mixedJavaRelease' instead.", mainJavaRelease
+ ));
+ }
+ project.afterEvaluate(p -> configureStandardJavaRelease(mainJavaRelease));
+ }
+
+ private void configureStandardJavaRelease(int mainJavaRelease) {
+ JavaCompile compileJava = helper().compileJavaTask(JavaPlugin.COMPILE_JAVA_TASK_NAME);
+ setJavaRelease(compileJava, mainJavaRelease);
+ }
+ //endregion
+
+ //region MIXED JAVA RELEASE
+ @Override
+ public void mixedJavaRelease(int mainJavaRelease, int moduleInfoJavaRelease) {
+ validateMixedJavaReleaseArgs(mainJavaRelease, moduleInfoJavaRelease);
+
+ CompileModuleOptions moduleOptions = helper().compileJavaTask(JavaPlugin.COMPILE_JAVA_TASK_NAME)
+ .getExtensions().getByType(CompileModuleOptions.class);
+ moduleOptions.setCompileModuleInfoSeparately(true);
+
+ project.afterEvaluate(p -> configureMixedJavaRelease(mainJavaRelease, moduleInfoJavaRelease));
+ }
+
+ private static void validateMixedJavaReleaseArgs(int mainJavaRelease, int moduleInfoJavaRelease) {
+ if (mainJavaRelease < 6) {
+ throw new IllegalArgumentException("Invalid main --release value: " + mainJavaRelease);
+ }
+ if (mainJavaRelease > 8) {
+ throw new IllegalArgumentException(String.format(
+ "Invalid main --release value: %d. Use 'standardJavaRelease' instead.", mainJavaRelease
+ ));
+ }
+ if (moduleInfoJavaRelease < 9) {
+ throw new IllegalArgumentException("Invalid module-info --release value: " + moduleInfoJavaRelease);
+ }
+ }
+
+ private void configureMixedJavaRelease(int mainJavaRelease, int moduleInfoJavaRelease) {
+ var compileJava = helper().compileJavaTask(JavaPlugin.COMPILE_JAVA_TASK_NAME);
+ setJavaRelease(compileJava, mainJavaRelease);
+
+ var compileModuleInfoJava = helper().compileJavaTask(CompileModuleOptions.COMPILE_MODULE_INFO_TASK_NAME);
+ setJavaRelease(compileModuleInfoJava, moduleInfoJavaRelease);
+ }
+ //endregion
+
+ // TODO: Remove this method when Gradle supports it natively: https://github.com/gradle/gradle/issues/2510
+ private void setJavaRelease(JavaCompile javaCompile, int javaRelease) {
+ String currentJavaVersion = JavaVersion.current().toString();
+ if (!javaCompile.getSourceCompatibility().equals(currentJavaVersion)) {
+ throw new IllegalStateException("sourceCompatibility should not be set together with --release option");
+ }
+ if (!javaCompile.getTargetCompatibility().equals(currentJavaVersion)) {
+ throw new IllegalStateException("targetCompatibility should not be set together with --release option");
+ }
+
+ List