Use module path instead of class path for stdlib on Java 9

Also report the "named does not read unnamed" error, which was not
possible previously because we wouldn't be able to read anything from
kotlin-stdlib (because it was added to the unnamed module by default)
This commit is contained in:
Alexander Udalov
2017-07-07 18:25:06 +03:00
parent c94b21edd5
commit 03a6488464
16 changed files with 118 additions and 37 deletions
@@ -30,10 +30,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
@@ -106,11 +103,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
}
val classpath = getClasspath(paths, arguments)
configuration.addJvmClasspathRoots(classpath)
for (modularRoot in arguments.javaModulePath?.split(File.pathSeparatorChar).orEmpty()) {
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(File(modularRoot)))
}
configureContentRoots(paths, arguments, configuration)
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
@@ -383,21 +376,35 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
arguments.declarationsOutputPath?.let { configuration.put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
}
private fun getClasspath(paths: KotlinPaths, arguments: K2JVMCompilerArguments): List<File> {
val classpath = arrayListOf<File>()
if (arguments.classpath != null) {
classpath.addAll(arguments.classpath.split(File.pathSeparatorChar).map(::File))
private fun configureContentRoots(paths: KotlinPaths, arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration) {
for (path in arguments.classpath?.split(File.pathSeparatorChar).orEmpty()) {
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(File(path)))
}
for (modularRoot in arguments.javaModulePath?.split(File.pathSeparatorChar).orEmpty()) {
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(File(modularRoot)))
}
val isModularJava = configuration.get(JVMConfigurationKeys.JDK_HOME).let { it != null && CoreJrtFileSystem.isModularJdk(it) }
fun addRoot(moduleName: String, file: File) {
if (isModularJava) {
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmModulePathRoot(file))
configuration.add(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, moduleName)
}
else {
configuration.add(JVMConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(file))
}
}
if (!arguments.noStdlib) {
classpath.add(paths.runtimePath)
classpath.add(paths.scriptRuntimePath)
addRoot("kotlin.stdlib", paths.stdlibPath)
addRoot("kotlin.script.runtime", paths.scriptRuntimePath)
}
// "-no-stdlib" implies "-no-reflect": otherwise we would be able to transitively read stdlib classes through kotlin-reflect,
// which is likely not what user wants since s/he manually provided "-no-stdlib"
if (!arguments.noReflect && !arguments.noStdlib) {
classpath.add(paths.reflectPath)
addRoot("kotlin.reflect", paths.reflectPath)
}
return classpath
}
private fun setupJdkClasspathRoots(arguments: K2JVMCompilerArguments, configuration: CompilerConfiguration, messageCollector: MessageCollector): ExitCode {
@@ -52,7 +52,7 @@ internal class ClasspathRootsResolver(
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?
) {
private val javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
val javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
data class RootsAndModules(val roots: List<JavaRoot>, val modules: List<JavaModule>)
@@ -229,7 +229,8 @@ class KotlinCoreEnvironment private constructor(
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules)
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules,
classpathRootsResolver.javaModuleFinder.systemModules.toList())
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.KotlinFileType
@@ -27,24 +28,31 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
class CliJavaModuleResolver(
private val moduleGraph: JavaModuleGraph,
private val javaModules: List<JavaModule>
private val userModules: List<JavaModule>,
private val systemModules: List<JavaModule.Explicit>
) : JavaModuleResolver {
init {
assert(javaModules.count { !it.isBinary } <= 1) {
"Modules computed by ClasspathRootsResolver cannot have more than one source module: $javaModules"
assert(userModules.count { !it.isBinary } <= 1) {
"Modules computed by ClasspathRootsResolver cannot have more than one source module: $userModules"
}
}
private val sourceModule = javaModules.firstOrNull { !it.isBinary }
private val sourceModule: JavaModule? = userModules.firstOrNull { !it.isBinary }
private fun findJavaModule(file: VirtualFile): JavaModule? =
when (file.fileType) {
KotlinFileType.INSTANCE, JavaFileType.INSTANCE -> sourceModule
JavaClassFileType.INSTANCE -> javaModules.firstOrNull { module ->
module.isBinary && VfsUtilCore.isAncestor(module.moduleRoot, file, false)
}
else -> null
}
private fun findJavaModule(file: VirtualFile): JavaModule? {
if (file.fileSystem.protocol == StandardFileSystems.JRT_PROTOCOL) {
return systemModules.firstOrNull { module -> file in module }
}
return when (file.fileType) {
KotlinFileType.INSTANCE, JavaFileType.INSTANCE -> sourceModule
JavaClassFileType.INSTANCE -> userModules.firstOrNull { module -> module.isBinary && file in module }
else -> null
}
}
private operator fun JavaModule.contains(file: VirtualFile): Boolean =
VfsUtilCore.isAncestor(moduleRoot, file, false)
override fun checkAccessibility(
fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName?