Support -Xmodule-path and -Xadd-modules command line arguments

#KT-18598 In Progress
 #KT-18599 Fixed
This commit is contained in:
Alexander Udalov
2017-05-26 15:20:05 +03:00
parent e32880d9a3
commit 03d83db660
43 changed files with 355 additions and 14 deletions
@@ -30,6 +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
@@ -106,6 +107,9 @@ 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)))
}
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
@@ -299,6 +303,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, components)
}
}
arguments.additionalJavaModules?.let { additionalJavaModules ->
configuration.addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, additionalJavaModules.toList())
}
}
override fun createArguments(): K2JVMCompilerArguments = K2JVMCompilerArguments().apply {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.config.ContentRoot
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo
internal class ClasspathRootsResolver(
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?
) {
private val javaModuleFinder = CliJavaModuleFinder(VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL))
@@ -75,6 +77,15 @@ internal class ClasspathRootsResolver(
is JvmClasspathRoot -> {
result += JavaRoot(root, JavaRoot.RootType.BINARY)
}
is JvmModulePathRoot -> {
// TODO: sanitize the automatic module name exactly as in javac
// TODO: read Automatic-Module-Name manifest entry
val module = modularBinaryRoot(root, automaticModuleName = { contentRoot.file.name })
if (module != null) {
// TODO: report something in case of several modules with the same name?
modules += module
}
}
else -> error("Unknown root type: $contentRoot")
}
}
@@ -97,6 +108,17 @@ internal class ClasspathRootsResolver(
return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), root, moduleInfoFile, isBinary = false)
}
private fun modularBinaryRoot(root: VirtualFile, automaticModuleName: () -> String): JavaModule? {
val moduleInfoFile = root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
return if (moduleInfoFile != null) {
val moduleInfo = JavaModuleInfo.read(moduleInfoFile) ?: return null
JavaModule.Explicit(moduleInfo, root, moduleInfoFile, isBinary = true)
}
else {
JavaModule.Automatic(automaticModuleName(), root)
}
}
private fun addModularRoots(modules: List<JavaModule>, result: MutableList<JavaRoot>) {
val sourceModules = modules.filterIsInstance<JavaModule.Explicit>().filterNot(JavaModule::isBinary)
if (sourceModules.size > 1) {
@@ -113,12 +135,17 @@ internal class ClasspathRootsResolver(
if (javaModuleFinder.allObservableModules.none()) return
val rootModules =
if (sourceModules.isNotEmpty()) {
// TODO: support an option similar to --add-modules
listOf(sourceModules.single().name)
}
else computeDefaultRootModules() // TODO: + everything from module path
val addAllModulePathToRoots = "ALL-MODULE-PATH" in additionalModules
if (addAllModulePathToRoots && sourceModules.isNotEmpty()) {
report(ERROR, "-Xadd-modules=ALL-MODULE-PATH can only be used when compiling the unnamed module")
return
}
val rootModules = when {
sourceModules.isNotEmpty() -> listOf(sourceModules.single().name) + additionalModules
addAllModulePathToRoots -> modules.map(JavaModule::name)
else -> computeDefaultRootModules() + modules.map(JavaModule::name)
}
// TODO: if at least one automatic module is added, add all automatic modules as per java.lang.module javadoc
val allDependencies = javaModuleGraph.getAllDependencies(rootModules).also { loadedModules ->
@@ -194,7 +194,11 @@ class KotlinCoreEnvironment private constructor(
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
classpathRootsResolver = ClasspathRootsResolver(PsiManager.getInstance(project), messageCollector, this::contentRootToVirtualFile)
classpathRootsResolver = ClasspathRootsResolver(
PsiManager.getInstance(project), messageCollector,
configuration.getList(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES),
this::contentRootToVirtualFile
)
val (initialRoots, javaModules) =
classpathRootsResolver.convertClasspathRoots(configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS))
@@ -304,7 +308,8 @@ class KotlinCoreEnvironment private constructor(
private fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? {
return when (root) {
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root) else findLocalFile(root)
is JvmClasspathRoot -> if (root.file.isFile) findJarRoot(root.file) else findLocalFile(root)
is JvmModulePathRoot -> if (root.file.isFile) findJarRoot(root.file) else findLocalFile(root)
is JavaSourceRoot -> findLocalFile(root)
else -> throw IllegalStateException("Unexpected root: $root")
}
@@ -320,8 +325,8 @@ class KotlinCoreEnvironment private constructor(
}
}
private fun findJarRoot(root: JvmClasspathRoot): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("${root.file}${URLUtil.JAR_SEPARATOR}")
private fun findJarRoot(file: File): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}")
private fun getSourceRootsCheckingForDuplicates(): Collection<String> {
val uniqueSourceRoots = linkedSetOf<String>()
@@ -30,6 +30,8 @@ data class JvmClasspathRoot(override val file: File) : JvmContentRoot
data class JavaSourceRoot(override val file: File, val packagePrefix: String?) : JvmContentRoot
data class JvmModulePathRoot(override val file: File) : JvmContentRoot
fun CompilerConfiguration.addJvmClasspathRoot(file: File) {
add(JVMConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(file))
}