diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt index fd4de77bda5..dc9a3000100 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt @@ -42,7 +42,9 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleGraph import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo import java.io.File import java.io.IOException +import java.util.jar.Attributes import java.util.jar.Manifest +import kotlin.LazyThreadSafetyMode.NONE internal class ClasspathRootsResolver( private val psiManager: PsiManager, @@ -111,26 +113,25 @@ internal class ClasspathRootsResolver( } private fun modularBinaryRoot(root: VirtualFile, originalFile: File): JavaModule? { + val isJar = root.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL + val manifest: Attributes? by lazy(NONE) { readManifestAttributes(root) } + val moduleInfoFile = root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) - ?: root.takeIf { it.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL } - ?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE) + ?: root.takeIf { isJar }?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE)?.takeIf { + manifest?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true) == true + } + if (moduleInfoFile != null) { val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null return JavaModule.Explicit(moduleInfo, root, moduleInfoFile, isBinary = true) } // Only .jar files can be automatic modules - if (originalFile.extension == StandardFileSystems.JAR_PROTOCOL) { - val manifestFile = root.findChild("META-INF")?.findChild("MANIFEST.MF") - if (manifestFile != null) { - try { - val moduleName = Manifest(manifestFile.inputStream).mainAttributes.getValue(AUTOMATIC_MODULE_NAME) - return JavaModule.Automatic(moduleName, root) - } - catch (e: IOException) { - return null - } + if (isJar) { + val automaticModuleName = manifest?.getValue(AUTOMATIC_MODULE_NAME) + if (automaticModuleName != null) { + return JavaModule.Automatic(automaticModuleName, root) } val moduleName = LightJavaModule.moduleName(originalFile.nameWithoutExtension) @@ -144,6 +145,16 @@ internal class ClasspathRootsResolver( return null } + private fun readManifestAttributes(jarRoot: VirtualFile): Attributes? { + val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF") + return try { + manifestFile?.inputStream?.let(::Manifest)?.mainAttributes + } + catch (e: IOException) { + null + } + } + private fun addModularRoots(modules: List, result: MutableList) { val sourceModules = modules.filterIsInstance().filterNot(JavaModule::isBinary) if (sourceModules.size > 1) { @@ -256,5 +267,6 @@ internal class ClasspathRootsResolver( private companion object { const val MULTI_RELEASE_MODULE_INFO_CLS_FILE = "META-INF/versions/9/${PsiJavaModule.MODULE_INFO_CLS_FILE}" const val AUTOMATIC_MODULE_NAME = "Automatic-Module-Name" + const val IS_MULTI_RELEASE = "Multi-Release" } } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java9ModulesIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java9ModulesIntegrationTest.kt index c2c88c2ce43..fa38e6f3c50 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java9ModulesIntegrationTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java9ModulesIntegrationTest.kt @@ -181,7 +181,8 @@ class Java9ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() { libraryOut9.mkdirs() File(libraryOut, "module-info.class").renameTo(File(libraryOut9, "module-info.class")) - val libraryJar = createMultiReleaseJar(jdk9Home, File(tmpdir, "library.jar"), libraryOut, libraryOut9) + // Use the name other from 'library' to prevent it from being loaded as an automatic module if module-info.class is not found + val libraryJar = createMultiReleaseJar(jdk9Home, File(tmpdir, "multi-release-library.jar"), libraryOut, libraryOut9) module("main", listOf(libraryJar)) }