CLI: load module-info from META-INF/versions/... for any version
Not just 9, since at least some libraries are putting module-info to META-INF/versions/11 nowadays. #KT-48027 Fixed
This commit is contained in:
@@ -156,13 +156,11 @@ class ClasspathRootsResolver(
|
||||
|
||||
private fun modularBinaryRoot(root: VirtualFile): JavaModule? {
|
||||
val isJar = root.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL
|
||||
val manifest: Attributes? by lazy(NONE) { readManifestAttributes(root) }
|
||||
val manifest = lazy(NONE) { readManifestAttributes(root) }
|
||||
|
||||
val moduleInfoFile =
|
||||
root.findChild(PsiJavaModule.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 (isJar) tryLoadVersionSpecificModuleInfo(root, manifest) else null
|
||||
|
||||
if (moduleInfoFile != null) {
|
||||
val moduleInfo = JavaModuleInfo.read(moduleInfoFile, javaFileManager, searchScope) ?: return null
|
||||
@@ -173,7 +171,7 @@ class ClasspathRootsResolver(
|
||||
if (isJar) {
|
||||
val moduleRoot = listOf(JavaModule.Root(root, isBinary = true))
|
||||
|
||||
val automaticModuleName = manifest?.getValue(AUTOMATIC_MODULE_NAME)
|
||||
val automaticModuleName = manifest.value?.getValue(AUTOMATIC_MODULE_NAME)
|
||||
if (automaticModuleName != null) {
|
||||
return JavaModule.Automatic(automaticModuleName, moduleRoot)
|
||||
}
|
||||
@@ -190,6 +188,23 @@ class ClasspathRootsResolver(
|
||||
return null
|
||||
}
|
||||
|
||||
private fun tryLoadVersionSpecificModuleInfo(root: VirtualFile, manifest: Lazy<Attributes?>): VirtualFile? {
|
||||
val versionsDir = root.findChild("META-INF")?.findChild("versions") ?: return null
|
||||
|
||||
val isMultiReleaseJar = manifest.value?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true)
|
||||
if (isMultiReleaseJar != true) return null
|
||||
|
||||
val versions = versionsDir.children.filter {
|
||||
val version = it.name.toIntOrNull()
|
||||
version != null && version >= 9
|
||||
}.sortedBy { it.name.toInt() }
|
||||
for (version in versions) {
|
||||
val file = version.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
|
||||
if (file != null) return file
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun readManifestAttributes(jarRoot: VirtualFile): Attributes? {
|
||||
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
|
||||
return try {
|
||||
@@ -323,7 +338,6 @@ 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"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.jar.Manifest
|
||||
import kotlin.test.fail
|
||||
|
||||
class Java11ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() {
|
||||
override val testDataPath: String
|
||||
@@ -78,13 +79,13 @@ class Java11ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun createMultiReleaseJar(jdk9Home: File, destination: File, mainRoot: File, java9Root: File): File {
|
||||
private fun createMultiReleaseJar(jdkHome: File, destination: File, mainRoot: File, version: Int, versionSpecificRoot: File): File {
|
||||
val command = listOf<String>(
|
||||
File(jdk9Home, "bin/jar").path,
|
||||
"--create", "--file=$destination",
|
||||
"-C", mainRoot.path, ".",
|
||||
"--release", "9",
|
||||
"-C", java9Root.path, "."
|
||||
File(jdkHome, "bin/jar").path,
|
||||
"--create", "--file=$destination",
|
||||
"-C", mainRoot.path, ".",
|
||||
"--release", version.toString(),
|
||||
"-C", versionSpecificRoot.path, "."
|
||||
)
|
||||
|
||||
val process = ProcessBuilder().command(command).inheritIO().start()
|
||||
@@ -124,8 +125,7 @@ class Java11ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() {
|
||||
fun testAllModulePathAndNamedModule() {
|
||||
try {
|
||||
module("main", addModules = listOf("ALL-MODULE-PATH"))
|
||||
}
|
||||
catch (e: JavaCompilationError) {
|
||||
} catch (e: JavaCompilationError) {
|
||||
// Java compilation should fail, it's expected
|
||||
}
|
||||
}
|
||||
@@ -176,10 +176,10 @@ class Java11ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() {
|
||||
"-Xmodule-path=${a.path}"
|
||||
)
|
||||
compileLibrary(
|
||||
"moduleB",
|
||||
additionalOptions = kotlinOptions,
|
||||
compileJava = { _, _, _ -> error("No .java files in moduleB in this test") },
|
||||
checkKotlinOutput = checkKotlinOutput("moduleB")
|
||||
"moduleB",
|
||||
additionalOptions = kotlinOptions,
|
||||
compileJava = { _, _, _ -> error("No .java files in moduleB in this test") },
|
||||
checkKotlinOutput = checkKotlinOutput("moduleB")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -192,12 +192,17 @@ class Java11ModulesIntegrationTest : AbstractKotlinCompilerIntegrationTest() {
|
||||
libraryOut11.mkdirs()
|
||||
File(libraryOut, "module-info.class").renameTo(File(libraryOut11, "module-info.class"))
|
||||
|
||||
// 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(
|
||||
KtTestUtil.getJdk11Home(), File(tmpdir, "multi-release-library.jar"), libraryOut, libraryOut11
|
||||
)
|
||||
|
||||
module("main", listOf(libraryJar))
|
||||
for (version in listOf(9, 10, 11)) {
|
||||
try {
|
||||
// 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(
|
||||
KtTestUtil.getJdk11Home(), File(tmpdir, "multi-release-library-jdk$version.jar"), libraryOut, version, libraryOut11
|
||||
)
|
||||
module("main", listOf(libraryJar))
|
||||
} catch (e: Throwable) {
|
||||
fail("Fail on testing that module-info.class is loaded from META-INF/versions/$version", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testAutomaticModuleNames() {
|
||||
|
||||
Reference in New Issue
Block a user