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 f68acfbc53f..1e61545d3f6 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 @@ -129,7 +129,7 @@ class ClasspathRootsResolver( addModularRoots(modules, result) } else { //TODO: see also `addJvmSdkRoots` usages, some refactoring is required with moving such logic into one place - val listFoldersForRelease = javaModuleFinder.listFoldersForRelease() + val listFoldersForRelease = javaModuleFinder.listFoldersForRelease listFoldersForRelease.forEach { result += JavaRoot(it, JavaRoot.RootType.BINARY_SIG) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt index 4802d038fd9..c6f47c1423e 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt @@ -102,6 +102,9 @@ class CliJavaModuleFinder( val allObservableModules: Sequence get() = systemModules + userModules.values + //Cache system modules for JDK 9-11 to preserve virtual files as one folder could be mapped to several modules + private val systemModulesCache = mutableMapOf() + val systemModules: Sequence get() = if (useLastJdkApi) modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule) else ctSymModules.values.asSequence().mapNotNull { findSystemModule(it, true) } @@ -116,15 +119,18 @@ class CliJavaModuleFinder( val file = moduleRoot.findChild(if (useSig) PsiJavaModule.MODULE_INFO_CLASS + ".sig" else PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null val moduleInfo = JavaModuleInfo.read(file, javaFileManager, allScope) ?: return null - return JavaModule.Explicit( - moduleInfo, - when { - useLastJdkApi -> listOf(JavaModule.Root(moduleRoot, isBinary = true, isBinarySignature = useSig)) - useSig -> createModuleFromSignature(moduleInfo) - else -> error("Can't find ${moduleRoot.path} module") - }, - file, true - ) + return systemModulesCache.getOrPut(moduleInfo.moduleName) { + JavaModule.Explicit( + moduleInfo, + when { + useLastJdkApi -> listOf(JavaModule.Root(moduleRoot, isBinary = true, isBinarySignature = useSig)) + useSig -> createModuleFromSignature(moduleInfo) + else -> error("Can't find ${moduleRoot.path} module") + }, + file, true + ) + } + } private fun createModuleFromSignature(moduleInfo: JavaModuleInfo): List { @@ -143,10 +149,16 @@ class CliJavaModuleFinder( } - return listFoldersForRelease().map { virtualFile -> + return listFoldersForRelease.mapNotNull { virtualFile -> + val rootFolder = when { + isCompilationJDK12OrLater -> if (virtualFile.name == moduleInfo.moduleName) virtualFile else return@mapNotNull null + else -> { + if (virtualFile.children.none { it.name in packageParts }) return@mapNotNull null + ModuleVirtualFileForRootPart(virtualFile.parent, virtualFile, packageParts, "") + } + } JavaModule.Root( - if (isCompilationJDK12OrLater) virtualFile - else ModuleVirtualFileForRootPart(virtualFile.parent, virtualFile, packageParts, ""), + rootFolder, isBinary = true, isBinarySignature = true ) @@ -158,9 +170,9 @@ class CliJavaModuleFinder( private fun matchesRelease(fileName: String, release: Int) = !fileName.contains("-") && fileName.contains(codeFor(release)) // skip `*-modules` - fun listFoldersForRelease(): List { - if (ctSymRootFolder == null) return emptyList() - return ctSymRootFolder!!.children.filter { matchesRelease(it.name, jdkRelease!!) }.flatMap { + val listFoldersForRelease: List by lazy { + if (ctSymRootFolder == null) emptyList() + else ctSymRootFolder!!.children.filter { matchesRelease(it.name, jdkRelease!!) }.flatMap { if (isCompilationJDK12OrLater) it.children.toList() else { @@ -174,7 +186,7 @@ class CliJavaModuleFinder( private fun collectModuleRoots(): Map { val result = mutableMapOf() if (isCompilationJDK12OrLater) { - listFoldersForRelease().forEach { modulesRoot -> + listFoldersForRelease.forEach { modulesRoot -> modulesRoot.findChild("module-info.sig")?.let { result[modulesRoot.name] = modulesRoot } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleResolver.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleResolver.kt index e3ea14f7f90..1922e872c02 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleResolver.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleResolver.kt @@ -54,7 +54,7 @@ class CliJavaModuleResolver( private val sourceModule: JavaModule? = userModules.firstOrNull(JavaModule::isSourceModule) private fun findJavaModule(file: VirtualFile): JavaModule? { - if (file.fileSystem.protocol == StandardFileSystems.JRT_PROTOCOL) { + if (file.fileSystem.protocol == StandardFileSystems.JRT_PROTOCOL || file.extension == "sig") { return systemModules.firstOrNull { module -> file in module } } diff --git a/compiler/testData/javaModules/releaseFlag/module17.txt b/compiler/testData/javaModules/releaseFlag/module17.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module17.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/releaseFlag/module17/foo/Foo.kt b/compiler/testData/javaModules/releaseFlag/module17/foo/Foo.kt new file mode 100644 index 00000000000..6e0c43fe410 --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module17/foo/Foo.kt @@ -0,0 +1,5 @@ +package foo; + +public class Foo { + val z: java.nio.ByteBuffer? = null +} diff --git a/compiler/testData/javaModules/releaseFlag/module17/module-info.java b/compiler/testData/javaModules/releaseFlag/module17/module-info.java new file mode 100644 index 00000000000..0c47b1d66f8 --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module17/module-info.java @@ -0,0 +1,5 @@ +module module17 { + exports foo; + + requires kotlin.stdlib; +} diff --git a/compiler/testData/javaModules/releaseFlag/module9.txt b/compiler/testData/javaModules/releaseFlag/module9.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module9.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/javaModules/releaseFlag/module9/foo/Foo.kt b/compiler/testData/javaModules/releaseFlag/module9/foo/Foo.kt new file mode 100644 index 00000000000..6e0c43fe410 --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module9/foo/Foo.kt @@ -0,0 +1,5 @@ +package foo; + +public class Foo { + val z: java.nio.ByteBuffer? = null +} diff --git a/compiler/testData/javaModules/releaseFlag/module9/module-info.java b/compiler/testData/javaModules/releaseFlag/module9/module-info.java new file mode 100644 index 00000000000..70b08a8899b --- /dev/null +++ b/compiler/testData/javaModules/releaseFlag/module9/module-info.java @@ -0,0 +1,5 @@ +module module9 { + exports foo; + + requires kotlin.stdlib; +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java11ModulesIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java11ModulesIntegrationTest.kt new file mode 100644 index 00000000000..2b3744a8396 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java11ModulesIntegrationTest.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler + +import org.jetbrains.kotlin.test.util.KtTestUtil + +class Java11ModulesIntegrationTest : JavaModulesIntegrationTest(11, KtTestUtil.getJdk11Home()) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java17ModulesIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java17ModulesIntegrationTest.kt new file mode 100644 index 00000000000..169fc853287 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/Java17ModulesIntegrationTest.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler + +import org.jetbrains.kotlin.test.util.KtTestUtil + +class Java17ModulesIntegrationTest : JavaModulesIntegrationTest(17, KtTestUtil.getJdk17Home()) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JavaModulesIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JavaModulesIntegrationTest.kt index c198a60e604..7c3f4a8d478 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JavaModulesIntegrationTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JavaModulesIntegrationTest.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.jvm.compiler import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.cli.AbstractCliTest import org.jetbrains.kotlin.cli.AbstractCliTest.getNormalizedCompilerOutput -import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.util.KtTestUtil @@ -17,7 +16,8 @@ import java.util.concurrent.TimeUnit import java.util.jar.Manifest import kotlin.test.fail -abstract class JavaModulesIntegrationTest(private val jdkHome: File) : AbstractKotlinCompilerIntegrationTest() { +abstract class JavaModulesIntegrationTest(private val jdkVersion: Int, private val jdkHome: File) : + AbstractKotlinCompilerIntegrationTest() { override val testDataPath: String get() = "compiler/testData/javaModules/" @@ -59,11 +59,17 @@ abstract class JavaModulesIntegrationTest(private val jdkHome: File) : AbstractK ) } - private fun checkKotlinOutput(moduleName: String): (String) -> Unit = { actual -> - KotlinTestUtils.assertEqualsToFile( - File(testDataDirectory, "$moduleName.txt"), - getNormalizedCompilerOutput(actual, null, testDataPath).replace(System.getenv("JDK_11"), "\$JDK11") - ) + + private fun checkKotlinOutput(moduleName: String): (String) -> Unit { + val expectedFile = + File(testDataDirectory, "$moduleName.$jdkVersion.txt").takeIf { it.exists() } ?: File(testDataDirectory, "$moduleName.txt") + return { actual -> + KotlinTestUtils.assertEqualsToFile( + expectedFile, + getNormalizedCompilerOutput(actual, null, testDataPath).replace(System.getenv("JDK_11").replace("\\", "/"), "\$JDK11") + .replace(System.getenv("JDK_17").replace("\\", "/"), "\$JDK17") + ) + } } private data class ModuleRunResult(val stdout: String, val stderr: String) @@ -150,12 +156,18 @@ abstract class JavaModulesIntegrationTest(private val jdkHome: File) : AbstractK fun testReleaseFlagWrongValue() { module("module5", additionalKotlinArguments = listOf("-Xjdk-release=5")) - module("module12", additionalKotlinArguments = listOf("-Xjdk-release=12")) + if (jdkVersion == 11) { + module("module12", additionalKotlinArguments = listOf("-Xjdk-release=12")) + } } fun testReleaseFlag() { module("module") + module("module9", additionalKotlinArguments = listOf("-Xjdk-release=9")) module("module11", additionalKotlinArguments = listOf("-Xjdk-release=11")) + if (jdkVersion == 17) { + module("module17", additionalKotlinArguments = listOf("-Xjdk-release=17")) + } module("moduleSwing", additionalKotlinArguments = listOf("-Xjdk-release=9")) }