diff --git a/CHANGELOG.md b/CHANGELOG.md index 6074057..675802d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Extra Java Module Info Gradle Plugin - Changelog ## Version 1.13.2 +* [Fixed] [#179](https://github.com/gradlex-org/extra-java-module-info/issues/179) - Combine 'preserveExisting' and 'exports' * [Fixed] [#219](https://github.com/gradlex-org/extra-java-module-info/issues/219) - Combine 'preserveExisting' and 'removePackage' * [Fixed] [#223](https://github.com/gradlex-org/extra-java-module-info/issues/223) - Combine 'preserveExisting' and 'ignoreServiceProvider' diff --git a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java index 91da2ef..8ad570b 100644 --- a/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java +++ b/src/main/java/org/gradlex/javamodule/moduleinfo/ExtraJavaModuleInfoTransform.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.Collections; import java.util.GregorianCalendar; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -440,10 +441,11 @@ private byte[] addModuleInfo( ClassReader classReader = moduleInfo.preserveExisting && existingModuleInfo != null ? new ClassReader(existingModuleInfo) : null; ClassWriter classWriter = new ClassWriter(classReader, 0); - int openModule = moduleInfo.openModule ? Opcodes.ACC_OPEN : 0; - String moduleVersion = moduleInfo.getModuleVersion() == null ? version : moduleInfo.getModuleVersion(); if (classReader == null) { + int openModule = moduleInfo.openModule ? Opcodes.ACC_OPEN : 0; + String moduleVersion = moduleInfo.getModuleVersion() == null ? version : moduleInfo.getModuleVersion(); + classWriter.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null, null); ModuleVisitor moduleVisitor = classWriter.visitModule(moduleInfo.getModuleName(), openModule, moduleVersion); @@ -452,23 +454,28 @@ private byte[] addModuleInfo( moduleVisitor.visitEnd(); classWriter.visitEnd(); } else { + Set explicitlyHandledPackage = new HashSet<>(); + explicitlyHandledPackage.addAll(moduleInfo.exports.keySet()); + explicitlyHandledPackage.addAll(autoExportedPackages); + explicitlyHandledPackage.addAll(removedPackages); + ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9, classWriter) { @Override public ModuleVisitor visitModule(String name, int access, String version) { - ModuleVisitor moduleVisitor = super.visitModule(name, access, version); + ModuleVisitor moduleVisitor = cv.visitModule(name, access, version); return new ModuleVisitor(Opcodes.ASM9, moduleVisitor) { @Override public void visitPackage(String packaze) { if (!removedPackages.contains(pathToPackage(packaze))) { - super.visitPackage(packaze); + mv.visitPackage(packaze); } } @Override public void visitExport(String packaze, int access, String... modules) { - if (!removedPackages.contains(pathToPackage(packaze))) { - super.visitExport(packaze, access, modules); + if (!explicitlyHandledPackage.contains(pathToPackage(packaze))) { + mv.visitExport(packaze, access, modules); } } @@ -477,7 +484,7 @@ public void visitUse(String service) { String packaze = service.substring(0, service.lastIndexOf("/")); // if package is removed, also remove 'use' directives based on the package if (!removedPackages.contains(pathToPackage(packaze))) { - super.visitUse(service); + mv.visitUse(service); } } @@ -489,14 +496,14 @@ public void visitProvide(String service, String... providers) { .contains(p)) .toArray(String[]::new); if (filteredProviders.length > 0) { - super.visitProvide(service, filteredProviders); + mv.visitProvide(service, filteredProviders); } } @Override public void visitEnd() { - addModuleInfoEntries(moduleInfo, Collections.emptyMap(), autoExportedPackages, this); - super.visitEnd(); + addModuleInfoEntries(moduleInfo, Collections.emptyMap(), autoExportedPackages, mv); + mv.visitEnd(); } }; } diff --git a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RealModuleJarPreservePatchingFunctionalTest.groovy b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RealModuleJarPreservePatchingFunctionalTest.groovy index 48a29e8..8d00130 100644 --- a/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RealModuleJarPreservePatchingFunctionalTest.groovy +++ b/src/test/groovy/org/gradlex/javamodule/moduleinfo/test/RealModuleJarPreservePatchingFunctionalTest.groovy @@ -78,4 +78,38 @@ class RealModuleJarPreservePatchingFunctionalTest extends Specification { run() } + def "can replace a package export in a preserved module-info"() { + given: + buildFile << ''' + dependencies { + implementation("org.controlsfx:controlsfx:11.2.3") + // undeclared transitive dependencies of controlsfx + implementation("org.openjfx:javafx-base:11:linux") + implementation("org.openjfx:javafx-controls:11:linux") + implementation("org.openjfx:javafx-graphics:11:linux") + } + extraJavaModuleInfo { + // original module-info contains: exports impl.org.controlsfx.skin to org.controlsfx.samples; + module("org.controlsfx:controlsfx", "org.controlsfx.controls") { + preserveExisting() + exports("impl.org.controlsfx.skin") + } + } + ''' + file("src/main/java/module-info.java") << """ + module org.example { + requires org.controlsfx.controls; + } + """ + file("src/main/java/org/example/Main.java") << """ + package org.example; + public class Main { + impl.org.controlsfx.skin.DecorationPane pane; + public static void main(String[] args) {} + } + """ + + expect: + run() + } }