From cd12772bc56303ca356a9fc6738c88da36abd830 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 8 Aug 2018 12:33:44 +0200 Subject: [PATCH] Remove unneeded bunch files related to PsiJavaModule PSI for modules and related classes are already available in AS3.1 --- .../compiler/ClasspathRootsResolver.kt.as31 | 332 ------------ .../compiler/ClasspathRootsResolver.kt.as32 | 332 ------------ .../KotlinCliJavaFileManagerImpl.kt.as31 | 291 ----------- .../KotlinCliJavaFileManagerImpl.kt.as32 | 291 ----------- .../KotlinToJVMBytecodeCompiler.kt.as31 | 471 ------------------ .../KotlinToJVMBytecodeCompiler.kt.as32 | 471 ------------------ .../jvm/modules/CliJavaModuleFinder.kt.as31 | 48 -- .../jvm/modules/CliJavaModuleFinder.kt.as32 | 48 -- .../jvm/modules/JavaModuleInfo.kt.as31 | 89 ---- .../jvm/modules/JavaModuleInfo.kt.as32 | 89 ---- 10 files changed, 2462 deletions(-) delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as31 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as31 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as31 delete mode 100644 compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32 delete mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as31 delete mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32 diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as31 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as31 deleted file mode 100644 index c083e94bf00..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as31 +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiJavaModule -import com.intellij.psi.PsiManager -import com.intellij.psi.impl.light.LightJavaModule -import org.jetbrains.kotlin.cli.common.config.ContentRoot -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -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.cli.jvm.modules.JavaModuleGraph -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.isValidJavaFqName -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo -import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME -import java.io.IOException -import java.util.jar.Attributes -import java.util.jar.Manifest -import kotlin.LazyThreadSafetyMode.NONE - -class ClasspathRootsResolver( - private val psiManager: PsiManager, - private val messageCollector: MessageCollector?, - private val additionalModules: List, - private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?, - private val javaModuleFinder: CliJavaModuleFinder, - private val requireStdlibModule: Boolean, - private val outputDirectory: VirtualFile? -) { - val javaModuleGraph = JavaModuleGraph(javaModuleFinder) - - data class RootsAndModules(val roots: List, val modules: List) - - private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?) - - fun convertClasspathRoots(contentRoots: List): RootsAndModules { - val javaSourceRoots = mutableListOf() - val jvmClasspathRoots = mutableListOf() - val jvmModulePathRoots = mutableListOf() - - for (contentRoot in contentRoots) { - if (contentRoot !is JvmContentRoot) continue - val root = contentRootToVirtualFile(contentRoot) ?: continue - when (contentRoot) { - is JavaSourceRoot -> javaSourceRoots += RootWithPrefix(root, contentRoot.packagePrefix) - is JvmClasspathRoot -> jvmClasspathRoots += root - is JvmModulePathRoot -> jvmModulePathRoots += root - else -> error("Unknown root type: $contentRoot") - } - } - - return computeRoots(javaSourceRoots, jvmClasspathRoots, jvmModulePathRoots) - } - - private fun computeRoots( - javaSourceRoots: List, - jvmClasspathRoots: List, - jvmModulePathRoots: List - ): RootsAndModules { - val result = mutableListOf() - val modules = mutableListOf() - - val hasOutputDirectoryInClasspath = outputDirectory in jvmClasspathRoots || outputDirectory in jvmModulePathRoots - - for ((root, packagePrefix) in javaSourceRoots) { - val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath) - if (modularRoot != null) { - modules += modularRoot - } else { - result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix -> - if (isValidJavaFqName(prefix)) FqName(prefix) - else null.also { - report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix") - } - }) - } - } - - for (root in jvmClasspathRoots) { - result += JavaRoot(root, JavaRoot.RootType.BINARY) - } - - val outputDirectoryAddedAsPartOfModule = modules.any { module -> module.moduleRoots.any { it.file == outputDirectory } } - - for (root in jvmModulePathRoots) { - // Do not add output directory as a separate module if we're compiling an explicit named module. - // It's going to be included as a root of our module in modularSourceRoot. - if (outputDirectoryAddedAsPartOfModule && root == outputDirectory) continue - - val module = modularBinaryRoot(root) - if (module != null) { - modules += module - } - } - - addModularRoots(modules, result) - - return RootsAndModules(result, modules) - } - - /* - private fun findSourceModuleInfo(root: VirtualFile): Pair? { - val moduleInfoFile = - when { - root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE) - root.name == PsiJavaModule.MODULE_INFO_FILE -> root - else -> null - } ?: return null - - val psiFile = psiManager.findFile(moduleInfoFile) ?: return null - val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null - - return moduleInfoFile to psiJavaModule - } - */ - - private fun modularSourceRoot(root: VirtualFile, hasOutputDirectoryInClasspath: Boolean): JavaModule.Explicit? { - /* - val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null - val sourceRoot = JavaModule.Root(root, isBinary = false) - val roots = - if (hasOutputDirectoryInClasspath) - listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true)) - else listOf(sourceRoot) - return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile) - */ - return null - } - - private fun modularBinaryRoot(root: VirtualFile): 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 { 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, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile) - } - */ - - // Only .jar files can be automatic modules - if (isJar) { - val moduleRoot = listOf(JavaModule.Root(root, isBinary = true)) - - val automaticModuleName = manifest?.getValue(AUTOMATIC_MODULE_NAME) - if (automaticModuleName != null) { - return JavaModule.Automatic(automaticModuleName, moduleRoot) - } - - val originalFile = VfsUtilCore.virtualToIoFile(root) - val moduleName = LightJavaModule.moduleName(originalFile.nameWithoutExtension) - if (moduleName.isEmpty()) { - report(ERROR, "Cannot infer automatic module name for the file", VfsUtilCore.getVirtualFileForJar(root) ?: root) - return null - } - return JavaModule.Automatic(moduleName, moduleRoot) - } - - 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) { - // In current implementation, at most one source module is supported. This can be relaxed in the future if we support another - // compilation mode, similar to java's --module-source-path - val sourceModules = modules.filterIsInstance().filter(JavaModule::isSourceModule) - if (sourceModules.size > 1) { - for (module in sourceModules) { - report(ERROR, "Too many source module declarations found", module.moduleInfoFile) - } - return - } - - for (module in modules) { - val existing = javaModuleFinder.findModule(module.name) - if (existing == null) { - javaModuleFinder.addUserModule(module) - } else if (module.moduleRoots != existing.moduleRoots) { - fun JavaModule.getRootFile() = - moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it } - - val thisFile = module.getRootFile() - val existingFile = existing.getRootFile() - val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}" - report( - STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " + - "has been found earlier on the module path$atExistingPath", thisFile - ) - } - } - - if (javaModuleFinder.allObservableModules.none()) return - - val sourceModule = sourceModules.singleOrNull() - val addAllModulePathToRoots = "ALL-MODULE-PATH" in additionalModules - if (addAllModulePathToRoots && sourceModule != null) { - report(ERROR, "-Xadd-modules=ALL-MODULE-PATH can only be used when compiling the unnamed module") - return - } - - val rootModules = when { - sourceModule != null -> listOf(sourceModule.name) + additionalModules - addAllModulePathToRoots -> modules.map(JavaModule::name) - else -> computeDefaultRootModules() + additionalModules - } - - val allDependencies = javaModuleGraph.getAllDependencies(rootModules) - if (allDependencies.any { moduleName -> javaModuleFinder.findModule(moduleName) is JavaModule.Automatic }) { - // According to java.lang.module javadoc, if at least one automatic module is added to the module graph, - // all observable automatic modules should be added. - // There are no automatic modules in the JDK, so we select all automatic modules out of user modules - for (module in modules) { - if (module is JavaModule.Automatic) { - allDependencies += module.name - } - } - } - - report(LOGGING, "Loading modules: $allDependencies") - - for (moduleName in allDependencies) { - val module = javaModuleFinder.findModule(moduleName) - if (module == null) { - report(ERROR, "Module $moduleName cannot be found in the module graph") - } else { - for ((root, isBinary) in module.moduleRoots) { - result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE)) - } - } - } - - if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) { - report( - ERROR, - "The Kotlin standard library is not found in the module graph. " + - "Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition", - sourceModule.moduleInfoFile - ) - } - } - - // See http://openjdk.java.net/jeps/261 - private fun computeDefaultRootModules(): List { - val result = arrayListOf() - - val systemModules = javaModuleFinder.systemModules.associateBy(JavaModule::name) - val javaSeExists = "java.se" in systemModules - if (javaSeExists) { - // The java.se module is a root, if it exists. - result.add("java.se") - } - - fun JavaModule.Explicit.exportsAtLeastOnePackageUnqualified(): Boolean = moduleInfo.exports.any { it.toModules.isEmpty() } - - if (!javaSeExists) { - // If it does not exist then every java.* module on the upgrade module path or among the system modules - // that exports at least one package, without qualification, is a root. - for ((name, module) in systemModules) { - if (name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) { - result.add(name) - } - } - } - - for ((name, module) in systemModules) { - // Every non-java.* module on the upgrade module path or among the system modules that exports at least one package, - // without qualification, is also a root. - if (!name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) { - result.add(name) - } - } - - return result - } - - private fun report(severity: CompilerMessageSeverity, message: String, file: VirtualFile? = null) { - if (messageCollector == null) { - throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)") - } - messageCollector.report( - severity, message, - if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file)) - ) - } - - 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/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32 deleted file mode 100644 index c083e94bf00..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ClasspathRootsResolver.kt.as32 +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiJavaModule -import com.intellij.psi.PsiManager -import com.intellij.psi.impl.light.LightJavaModule -import org.jetbrains.kotlin.cli.common.config.ContentRoot -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -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.cli.jvm.modules.JavaModuleGraph -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.isValidJavaFqName -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo -import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME -import java.io.IOException -import java.util.jar.Attributes -import java.util.jar.Manifest -import kotlin.LazyThreadSafetyMode.NONE - -class ClasspathRootsResolver( - private val psiManager: PsiManager, - private val messageCollector: MessageCollector?, - private val additionalModules: List, - private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?, - private val javaModuleFinder: CliJavaModuleFinder, - private val requireStdlibModule: Boolean, - private val outputDirectory: VirtualFile? -) { - val javaModuleGraph = JavaModuleGraph(javaModuleFinder) - - data class RootsAndModules(val roots: List, val modules: List) - - private data class RootWithPrefix(val root: VirtualFile, val packagePrefix: String?) - - fun convertClasspathRoots(contentRoots: List): RootsAndModules { - val javaSourceRoots = mutableListOf() - val jvmClasspathRoots = mutableListOf() - val jvmModulePathRoots = mutableListOf() - - for (contentRoot in contentRoots) { - if (contentRoot !is JvmContentRoot) continue - val root = contentRootToVirtualFile(contentRoot) ?: continue - when (contentRoot) { - is JavaSourceRoot -> javaSourceRoots += RootWithPrefix(root, contentRoot.packagePrefix) - is JvmClasspathRoot -> jvmClasspathRoots += root - is JvmModulePathRoot -> jvmModulePathRoots += root - else -> error("Unknown root type: $contentRoot") - } - } - - return computeRoots(javaSourceRoots, jvmClasspathRoots, jvmModulePathRoots) - } - - private fun computeRoots( - javaSourceRoots: List, - jvmClasspathRoots: List, - jvmModulePathRoots: List - ): RootsAndModules { - val result = mutableListOf() - val modules = mutableListOf() - - val hasOutputDirectoryInClasspath = outputDirectory in jvmClasspathRoots || outputDirectory in jvmModulePathRoots - - for ((root, packagePrefix) in javaSourceRoots) { - val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath) - if (modularRoot != null) { - modules += modularRoot - } else { - result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix -> - if (isValidJavaFqName(prefix)) FqName(prefix) - else null.also { - report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix") - } - }) - } - } - - for (root in jvmClasspathRoots) { - result += JavaRoot(root, JavaRoot.RootType.BINARY) - } - - val outputDirectoryAddedAsPartOfModule = modules.any { module -> module.moduleRoots.any { it.file == outputDirectory } } - - for (root in jvmModulePathRoots) { - // Do not add output directory as a separate module if we're compiling an explicit named module. - // It's going to be included as a root of our module in modularSourceRoot. - if (outputDirectoryAddedAsPartOfModule && root == outputDirectory) continue - - val module = modularBinaryRoot(root) - if (module != null) { - modules += module - } - } - - addModularRoots(modules, result) - - return RootsAndModules(result, modules) - } - - /* - private fun findSourceModuleInfo(root: VirtualFile): Pair? { - val moduleInfoFile = - when { - root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE) - root.name == PsiJavaModule.MODULE_INFO_FILE -> root - else -> null - } ?: return null - - val psiFile = psiManager.findFile(moduleInfoFile) ?: return null - val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null - - return moduleInfoFile to psiJavaModule - } - */ - - private fun modularSourceRoot(root: VirtualFile, hasOutputDirectoryInClasspath: Boolean): JavaModule.Explicit? { - /* - val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null - val sourceRoot = JavaModule.Root(root, isBinary = false) - val roots = - if (hasOutputDirectoryInClasspath) - listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true)) - else listOf(sourceRoot) - return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile) - */ - return null - } - - private fun modularBinaryRoot(root: VirtualFile): 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 { 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, listOf(JavaModule.Root(root, isBinary = true)), moduleInfoFile) - } - */ - - // Only .jar files can be automatic modules - if (isJar) { - val moduleRoot = listOf(JavaModule.Root(root, isBinary = true)) - - val automaticModuleName = manifest?.getValue(AUTOMATIC_MODULE_NAME) - if (automaticModuleName != null) { - return JavaModule.Automatic(automaticModuleName, moduleRoot) - } - - val originalFile = VfsUtilCore.virtualToIoFile(root) - val moduleName = LightJavaModule.moduleName(originalFile.nameWithoutExtension) - if (moduleName.isEmpty()) { - report(ERROR, "Cannot infer automatic module name for the file", VfsUtilCore.getVirtualFileForJar(root) ?: root) - return null - } - return JavaModule.Automatic(moduleName, moduleRoot) - } - - 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) { - // In current implementation, at most one source module is supported. This can be relaxed in the future if we support another - // compilation mode, similar to java's --module-source-path - val sourceModules = modules.filterIsInstance().filter(JavaModule::isSourceModule) - if (sourceModules.size > 1) { - for (module in sourceModules) { - report(ERROR, "Too many source module declarations found", module.moduleInfoFile) - } - return - } - - for (module in modules) { - val existing = javaModuleFinder.findModule(module.name) - if (existing == null) { - javaModuleFinder.addUserModule(module) - } else if (module.moduleRoots != existing.moduleRoots) { - fun JavaModule.getRootFile() = - moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it } - - val thisFile = module.getRootFile() - val existingFile = existing.getRootFile() - val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}" - report( - STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " + - "has been found earlier on the module path$atExistingPath", thisFile - ) - } - } - - if (javaModuleFinder.allObservableModules.none()) return - - val sourceModule = sourceModules.singleOrNull() - val addAllModulePathToRoots = "ALL-MODULE-PATH" in additionalModules - if (addAllModulePathToRoots && sourceModule != null) { - report(ERROR, "-Xadd-modules=ALL-MODULE-PATH can only be used when compiling the unnamed module") - return - } - - val rootModules = when { - sourceModule != null -> listOf(sourceModule.name) + additionalModules - addAllModulePathToRoots -> modules.map(JavaModule::name) - else -> computeDefaultRootModules() + additionalModules - } - - val allDependencies = javaModuleGraph.getAllDependencies(rootModules) - if (allDependencies.any { moduleName -> javaModuleFinder.findModule(moduleName) is JavaModule.Automatic }) { - // According to java.lang.module javadoc, if at least one automatic module is added to the module graph, - // all observable automatic modules should be added. - // There are no automatic modules in the JDK, so we select all automatic modules out of user modules - for (module in modules) { - if (module is JavaModule.Automatic) { - allDependencies += module.name - } - } - } - - report(LOGGING, "Loading modules: $allDependencies") - - for (moduleName in allDependencies) { - val module = javaModuleFinder.findModule(moduleName) - if (module == null) { - report(ERROR, "Module $moduleName cannot be found in the module graph") - } else { - for ((root, isBinary) in module.moduleRoots) { - result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE)) - } - } - } - - if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) { - report( - ERROR, - "The Kotlin standard library is not found in the module graph. " + - "Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition", - sourceModule.moduleInfoFile - ) - } - } - - // See http://openjdk.java.net/jeps/261 - private fun computeDefaultRootModules(): List { - val result = arrayListOf() - - val systemModules = javaModuleFinder.systemModules.associateBy(JavaModule::name) - val javaSeExists = "java.se" in systemModules - if (javaSeExists) { - // The java.se module is a root, if it exists. - result.add("java.se") - } - - fun JavaModule.Explicit.exportsAtLeastOnePackageUnqualified(): Boolean = moduleInfo.exports.any { it.toModules.isEmpty() } - - if (!javaSeExists) { - // If it does not exist then every java.* module on the upgrade module path or among the system modules - // that exports at least one package, without qualification, is a root. - for ((name, module) in systemModules) { - if (name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) { - result.add(name) - } - } - } - - for ((name, module) in systemModules) { - // Every non-java.* module on the upgrade module path or among the system modules that exports at least one package, - // without qualification, is also a root. - if (!name.startsWith("java.") && module.exportsAtLeastOnePackageUnqualified()) { - result.add(name) - } - } - - return result - } - - private fun report(severity: CompilerMessageSeverity, message: String, file: VirtualFile? = null) { - if (messageCollector == null) { - throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)") - } - messageCollector.report( - severity, message, - if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file)) - ) - } - - 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/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as31 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as31 deleted file mode 100644 index 2f07c432925..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as31 +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.core.CoreJavaFileManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.* -import com.intellij.psi.impl.file.PsiPackageImpl -import com.intellij.psi.search.GlobalSearchScope -import gnu.trove.THashMap -import org.jetbrains.kotlin.cli.jvm.index.JavaRoot -import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex -import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.isNotTopLevelClass -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager -import org.jetbrains.kotlin.util.PerformanceCounter -import org.jetbrains.kotlin.utils.addIfNotNull -import java.util.* - -// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices -// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage, -// which is indirectly invoked from PsiPackage.getSubPackages -class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager { - private val perfCounter = PerformanceCounter.create("Find Java class") - private lateinit var index: JvmDependenciesIndex - private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex - private lateinit var packagePartProviders: List - private val topLevelClassesCache: MutableMap = THashMap() - private val allScope = GlobalSearchScope.allScope(myPsiManager.project) - private var useFastClassFilesReading = false - - fun initialize( - index: JvmDependenciesIndex, - packagePartProviders: List, - singleJavaFileRootsIndex: SingleJavaFileRootsIndex, - useFastClassFilesReading: Boolean - ) { - this.index = index - this.packagePartProviders = packagePartProviders - this.singleJavaFileRootsIndex = singleJavaFileRootsIndex - this.useFastClassFilesReading = useFastClassFilesReading - } - - private fun findPsiClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time { - findVirtualFileForTopLevelClass(classId, searchScope)?.findPsiClassInVirtualFile(classId.relativeClassName.asString()) - } - - private fun findVirtualFileForTopLevelClass(classId: ClassId, searchScope: GlobalSearchScope): VirtualFile? { - val relativeClassName = classId.relativeClassName.asString() - return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { - index.findClass(classId) { dir, type -> - findVirtualFileGivenPackage(dir, relativeClassName, type) - } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId) - }?.takeIf { it in searchScope } - } - - private val binaryCache: MutableMap = THashMap() - private val signatureParsingComponent = BinaryClassSignatureParser() - - override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? { - val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null - - if (useFastClassFilesReading && virtualFile.extension == "class") { - // We return all class files' names in the directory in knownClassNamesInPackage method, so one may request an inner class - return binaryCache.getOrPut(classId) { - // Note that currently we implicitly suppose that searchScope for binary classes is constant and we do not use it - // as a key in cache - // This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary - // When it become wrong because we introduce the modules into CLI, it's worth to consider - // having different KotlinCliJavaFileManagerImpl's for different modules - val classContent = virtualFile.contentsToByteArray() - if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null - classId.outerClassId?.let { outerClassId -> - val outerClass = findClass(outerClassId, searchScope) - return@getOrPut outerClass?.findInnerClass(classId.shortClassName) - } - - val resolver = ClassifierResolutionContext { findClass(it, allScope) } - - BinaryJavaClass( - virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent, - outerClass = null, classContent = classContent - ) - } - } - - return virtualFile.findPsiClassInVirtualFile(classId.relativeClassName.asString())?.let(::JavaClassImpl) - } - - // this method is called from IDEA to resolve dependencies in Java code - // which supposedly shouldn't have errors so the dependencies exist in general - override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? { - // String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin. - // For example, if qName is "a.b.c.d.e", we should either look for a top level class "e" in the package "a.b.c.d", - // or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b". - // Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package - // "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly - - forEachClassId(qName) { classId -> - findPsiClass(classId, scope)?.let { return it } - } - - return null - } - - private inline fun forEachClassId(fqName: String, block: (ClassId) -> Unit) { - var classId = fqName.toSafeTopLevelClassId() ?: return - - while (true) { - block(classId) - - val packageFqName = classId.packageFqName - if (packageFqName.isRoot) break - - classId = ClassId( - packageFqName.parent(), - FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()), - false - ) - } - } - - override fun findClasses(qName: String, scope: GlobalSearchScope): Array = perfCounter.time { - val result = ArrayList(1) - forEachClassId(qName) { classId -> - val relativeClassName = classId.relativeClassName.asString() - index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType -> - val psiClass = - findVirtualFileGivenPackage(dir, relativeClassName, rootType) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - if (psiClass != null) { - result.add(psiClass) - } - // traverse all - true - } - - result.addIfNotNull( - singleJavaFileRootsIndex.findJavaSourceClass(classId) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - ) - - if (result.isNotEmpty()) { - return@time result.toTypedArray() - } - } - - PsiClass.EMPTY_ARRAY - } - - override fun findPackage(packageName: String): PsiPackage? { - var found = false - val packageFqName = packageName.toSafeFqName() ?: return null - index.traverseDirectoriesInPackage(packageFqName) { _, _ -> - found = true - //abort on first found - false - } - if (!found) { - found = packagePartProviders.any { it.findPackageParts(packageName).isNotEmpty() } - } - if (!found) { - found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty() - } - return if (found) PsiPackageImpl(myPsiManager, packageName) else null - } - - private fun findVirtualFileGivenPackage( - packageDir: VirtualFile, - classNameWithInnerClasses: String, - rootType: JavaRoot.RootType - ): VirtualFile? { - val topLevelClassName = classNameWithInnerClasses.substringBefore('.') - - val vFile = when (rootType) { - JavaRoot.RootType.BINARY -> packageDir.findChild("$topLevelClassName.class") - JavaRoot.RootType.SOURCE -> packageDir.findChild("$topLevelClassName.java") - } ?: return null - - if (!vFile.isValid) { - LOG.error("Invalid child of valid parent: ${vFile.path}; ${packageDir.isValid} path=${packageDir.path}") - return null - } - - return vFile - } - - private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? { - val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null - return findClassInPsiFile(classNameWithInnerClasses, file) - } - - override fun knownClassNamesInPackage(packageFqName: FqName): Set { - val result = hashSetOf() - index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ -> - for (child in dir.children) { - if (child.extension == "class" || child.extension == "java") { - result.add(child.nameWithoutExtension) - } - } - - true - }) - - for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) { - assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" } - result.add(classId.shortClassName.asString()) - } - - return result - } - -/* - override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection { - // TODO - return emptySet() - } -*/ - - override fun getNonTrivialPackagePrefixes(): Collection = emptyList() - - companion object { - private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java) - - private fun findClassInPsiFile(classNameWithInnerClassesDotSeparated: String, file: PsiClassOwner): PsiClass? { - for (topLevelClass in file.classes) { - val candidate = findClassByTopLevelClass(classNameWithInnerClassesDotSeparated, topLevelClass) - if (candidate != null) { - return candidate - } - } - return null - } - - private fun findClassByTopLevelClass(className: String, topLevelClass: PsiClass): PsiClass? { - if (className.indexOf('.') < 0) { - return if (className == topLevelClass.name) topLevelClass else null - } - - val segments = StringUtil.split(className, ".").iterator() - if (!segments.hasNext() || segments.next() != topLevelClass.name) { - return null - } - var curClass = topLevelClass - while (segments.hasNext()) { - val innerClassName = segments.next() - val innerClass = curClass.findInnerClassByName(innerClassName, false) ?: return null - curClass = innerClass - } - return curClass - } - } -} - -// a sad workaround to avoid throwing exception when called from inside IDEA code -private fun safely(compute: () -> T): T? = - try { - compute() - } catch (e: IllegalArgumentException) { - null - } catch (e: AssertionError) { - null - } - -private fun String.toSafeFqName(): FqName? = safely { FqName(this) } -private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32 deleted file mode 100644 index 2f07c432925..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt.as32 +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.core.CoreJavaFileManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.* -import com.intellij.psi.impl.file.PsiPackageImpl -import com.intellij.psi.search.GlobalSearchScope -import gnu.trove.THashMap -import org.jetbrains.kotlin.cli.jvm.index.JavaRoot -import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex -import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.isNotTopLevelClass -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager -import org.jetbrains.kotlin.util.PerformanceCounter -import org.jetbrains.kotlin.utils.addIfNotNull -import java.util.* - -// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices -// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage, -// which is indirectly invoked from PsiPackage.getSubPackages -class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager { - private val perfCounter = PerformanceCounter.create("Find Java class") - private lateinit var index: JvmDependenciesIndex - private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex - private lateinit var packagePartProviders: List - private val topLevelClassesCache: MutableMap = THashMap() - private val allScope = GlobalSearchScope.allScope(myPsiManager.project) - private var useFastClassFilesReading = false - - fun initialize( - index: JvmDependenciesIndex, - packagePartProviders: List, - singleJavaFileRootsIndex: SingleJavaFileRootsIndex, - useFastClassFilesReading: Boolean - ) { - this.index = index - this.packagePartProviders = packagePartProviders - this.singleJavaFileRootsIndex = singleJavaFileRootsIndex - this.useFastClassFilesReading = useFastClassFilesReading - } - - private fun findPsiClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time { - findVirtualFileForTopLevelClass(classId, searchScope)?.findPsiClassInVirtualFile(classId.relativeClassName.asString()) - } - - private fun findVirtualFileForTopLevelClass(classId: ClassId, searchScope: GlobalSearchScope): VirtualFile? { - val relativeClassName = classId.relativeClassName.asString() - return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { - index.findClass(classId) { dir, type -> - findVirtualFileGivenPackage(dir, relativeClassName, type) - } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId) - }?.takeIf { it in searchScope } - } - - private val binaryCache: MutableMap = THashMap() - private val signatureParsingComponent = BinaryClassSignatureParser() - - override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? { - val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null - - if (useFastClassFilesReading && virtualFile.extension == "class") { - // We return all class files' names in the directory in knownClassNamesInPackage method, so one may request an inner class - return binaryCache.getOrPut(classId) { - // Note that currently we implicitly suppose that searchScope for binary classes is constant and we do not use it - // as a key in cache - // This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary - // When it become wrong because we introduce the modules into CLI, it's worth to consider - // having different KotlinCliJavaFileManagerImpl's for different modules - val classContent = virtualFile.contentsToByteArray() - if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null - classId.outerClassId?.let { outerClassId -> - val outerClass = findClass(outerClassId, searchScope) - return@getOrPut outerClass?.findInnerClass(classId.shortClassName) - } - - val resolver = ClassifierResolutionContext { findClass(it, allScope) } - - BinaryJavaClass( - virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent, - outerClass = null, classContent = classContent - ) - } - } - - return virtualFile.findPsiClassInVirtualFile(classId.relativeClassName.asString())?.let(::JavaClassImpl) - } - - // this method is called from IDEA to resolve dependencies in Java code - // which supposedly shouldn't have errors so the dependencies exist in general - override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? { - // String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin. - // For example, if qName is "a.b.c.d.e", we should either look for a top level class "e" in the package "a.b.c.d", - // or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b". - // Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package - // "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly - - forEachClassId(qName) { classId -> - findPsiClass(classId, scope)?.let { return it } - } - - return null - } - - private inline fun forEachClassId(fqName: String, block: (ClassId) -> Unit) { - var classId = fqName.toSafeTopLevelClassId() ?: return - - while (true) { - block(classId) - - val packageFqName = classId.packageFqName - if (packageFqName.isRoot) break - - classId = ClassId( - packageFqName.parent(), - FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()), - false - ) - } - } - - override fun findClasses(qName: String, scope: GlobalSearchScope): Array = perfCounter.time { - val result = ArrayList(1) - forEachClassId(qName) { classId -> - val relativeClassName = classId.relativeClassName.asString() - index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType -> - val psiClass = - findVirtualFileGivenPackage(dir, relativeClassName, rootType) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - if (psiClass != null) { - result.add(psiClass) - } - // traverse all - true - } - - result.addIfNotNull( - singleJavaFileRootsIndex.findJavaSourceClass(classId) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - ) - - if (result.isNotEmpty()) { - return@time result.toTypedArray() - } - } - - PsiClass.EMPTY_ARRAY - } - - override fun findPackage(packageName: String): PsiPackage? { - var found = false - val packageFqName = packageName.toSafeFqName() ?: return null - index.traverseDirectoriesInPackage(packageFqName) { _, _ -> - found = true - //abort on first found - false - } - if (!found) { - found = packagePartProviders.any { it.findPackageParts(packageName).isNotEmpty() } - } - if (!found) { - found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty() - } - return if (found) PsiPackageImpl(myPsiManager, packageName) else null - } - - private fun findVirtualFileGivenPackage( - packageDir: VirtualFile, - classNameWithInnerClasses: String, - rootType: JavaRoot.RootType - ): VirtualFile? { - val topLevelClassName = classNameWithInnerClasses.substringBefore('.') - - val vFile = when (rootType) { - JavaRoot.RootType.BINARY -> packageDir.findChild("$topLevelClassName.class") - JavaRoot.RootType.SOURCE -> packageDir.findChild("$topLevelClassName.java") - } ?: return null - - if (!vFile.isValid) { - LOG.error("Invalid child of valid parent: ${vFile.path}; ${packageDir.isValid} path=${packageDir.path}") - return null - } - - return vFile - } - - private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? { - val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null - return findClassInPsiFile(classNameWithInnerClasses, file) - } - - override fun knownClassNamesInPackage(packageFqName: FqName): Set { - val result = hashSetOf() - index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ -> - for (child in dir.children) { - if (child.extension == "class" || child.extension == "java") { - result.add(child.nameWithoutExtension) - } - } - - true - }) - - for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) { - assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" } - result.add(classId.shortClassName.asString()) - } - - return result - } - -/* - override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection { - // TODO - return emptySet() - } -*/ - - override fun getNonTrivialPackagePrefixes(): Collection = emptyList() - - companion object { - private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java) - - private fun findClassInPsiFile(classNameWithInnerClassesDotSeparated: String, file: PsiClassOwner): PsiClass? { - for (topLevelClass in file.classes) { - val candidate = findClassByTopLevelClass(classNameWithInnerClassesDotSeparated, topLevelClass) - if (candidate != null) { - return candidate - } - } - return null - } - - private fun findClassByTopLevelClass(className: String, topLevelClass: PsiClass): PsiClass? { - if (className.indexOf('.') < 0) { - return if (className == topLevelClass.name) topLevelClass else null - } - - val segments = StringUtil.split(className, ".").iterator() - if (!segments.hasNext() || segments.next() != topLevelClass.name) { - return null - } - var curClass = topLevelClass - while (segments.hasNext()) { - val innerClassName = segments.next() - val innerClass = curClass.findInnerClassByName(innerClassName, false) ?: return null - curClass = innerClass - } - return curClass - } - } -} - -// a sad workaround to avoid throwing exception when called from inside IDEA code -private fun safely(compute: () -> T): T? = - try { - compute() - } catch (e: IllegalArgumentException) { - null - } catch (e: AssertionError) { - null - } - -private fun String.toSafeFqName(): FqName? = safely { FqName(this) } -private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 deleted file mode 100644 index 543a088f8c2..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as31 +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiManager -import com.intellij.psi.impl.PsiModificationTrackerImpl -import com.intellij.psi.search.DelegatingGlobalSearchScope -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics -import org.jetbrains.kotlin.backend.common.output.OutputFileCollection -import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection -import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage -import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil -import org.jetbrains.kotlin.cli.common.output.writeAll -import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback -import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil -import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.javac.JavacWrapper -import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager -import org.jetbrains.kotlin.modules.Module -import org.jetbrains.kotlin.modules.TargetId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs -import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize -import java.io.File -import java.lang.reflect.InvocationTargetException -import java.net.URLClassLoader - -object KotlinToJVMBytecodeCompiler { - - private fun getAbsolutePaths(buildFile: File, module: Module): List { - return module.getSourceFiles().map { sourceFile -> - val source = File(sourceFile) - if (!source.isAbsolute) { - File(buildFile.absoluteFile.parentFile, sourceFile).absolutePath - } else { - source.absolutePath - } - } - } - - private fun writeOutput( - configuration: CompilerConfiguration, - outputFiles: OutputFileCollection, - mainClass: FqName? - ) { - val reportOutputFiles = configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES) - val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR) - val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) - if (jarPath != null) { - val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false) - CompileEnvironmentUtil.writeToJar(jarPath, includeRuntime, mainClass, outputFiles) - if (reportOutputFiles) { - val message = OutputMessageUtil.formatOutputMessage(outputFiles.asList().flatMap { it.sourceFiles }.distinct(), jarPath) - messageCollector.report(OUTPUT, message) - } - return - } - - val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".") - outputFiles.writeAll(outputDir, messageCollector, reportOutputFiles) - } - - private fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback { - if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) { - return GenerationStateEventCallback.DO_NOTHING - } - return GenerationStateEventCallback { state -> - val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput) - writeOutput(configuration, currentOutput, mainClass = null) - if (!configuration.get(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)) { - state.factory.releaseGeneratedOutput() - } - } - } - - internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File, chunk: List): Boolean { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) - - val projectConfiguration = environment.configuration - for (module in chunk) { - moduleVisibilityManager.addModule(module) - } - - val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) - for (path in friendPaths) { - moduleVisibilityManager.addFriendPath(path) - } - - val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]" - - val result = repeatAnalysisIfNeeded(analyze(environment, targetDescription), environment, targetDescription) - if (result == null || !result.shouldGenerateCode) return false - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - result.throwIfError() - - val outputs = newLinkedHashMapWithExpectedSize(chunk.size) - - for (module in chunk) { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val moduleSourcePaths = getAbsolutePaths(buildFile, module) - val ktFiles = environment.getSourceFiles().filter { file -> file.virtualFilePath in moduleSourcePaths } - - if (!checkKotlinPackageUsage(environment, ktFiles)) return false - - val moduleConfiguration = projectConfiguration.copy().apply { - put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory())) - } - - outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module) - } - - try { - for ((_, state) in outputs) { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - writeOutput(state.configuration, state.factory, null) - } - - if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) { - val singleModule = chunk.singleOrNull() - if (singleModule != null) { - return JavacWrapper.getInstance(environment.project).use { - it.compile(File(singleModule.getOutputDirectory())) - } - } else { - projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( - WARNING, - "A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " + - "-Xuse-javac option couldn't be used to compile java files" - ) - JavacWrapper.getInstance(environment.project).close() - } - } - - return true - } finally { - outputs.values.forEach(GenerationState::destroy) - } - } - - internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List, buildFile: File) { - for (module in chunk) { - configuration.addKotlinSourceRoots(getAbsolutePaths(buildFile, module)) - } - - for (module in chunk) { - for ((path, packagePrefix) in module.getJavaSourceRoots()) { - configuration.addJavaSourceRoot(File(path), packagePrefix) - } - } - - val isJava9Module = false /*chunk.any { module -> - module.getJavaSourceRoots().any { (path, packagePrefix) -> - val file = File(path) - packagePrefix == null && - (file.name == PsiJavaModule.MODULE_INFO_FILE || - (file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE })) - } - }*/ - - for (module in chunk) { - for (classpathRoot in module.getClasspathRoots()) { - configuration.add( - CLIConfigurationKeys.CONTENT_ROOTS, - if (isJava9Module) JvmModulePathRoot(File(classpathRoot)) else JvmClasspathRoot(File(classpathRoot)) - ) - } - } - - for (module in chunk) { - val modularJdkRoot = module.modularJdkRoot - if (modularJdkRoot != null) { - // We use the SDK of the first module in the chunk, which is not always correct because some other module in the chunk - // might depend on a different SDK - configuration.put(JVMConfigurationKeys.JDK_HOME, File(modularJdkRoot)) - break - } - } - - configuration.addAll(JVMConfigurationKeys.MODULES, chunk) - } - - private fun findMainClass(generationState: GenerationState, files: List): FqName? { - val mainFunctionDetector = MainFunctionDetector(generationState.bindingContext) - return files.asSequence() - .map { file -> - if (mainFunctionDetector.hasMain(file.declarations)) - JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName - else - null - } - .singleOrNull { it != null } - } - - fun compileBunchOfSources(environment: KotlinCoreEnvironment): Boolean { - val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) - - val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) - for (path in friendPaths) { - moduleVisibilityManager.addFriendPath(path) - } - - if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false - - val generationState = analyzeAndGenerate(environment) ?: return false - - val mainClass = findMainClass(generationState, environment.getSourceFiles()) - - try { - writeOutput(environment.configuration, generationState.factory, mainClass) - return true - } finally { - generationState.destroy() - } - } - - internal fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List): ExitCode { - val scriptClass = compileScript(environment) ?: return ExitCode.COMPILATION_ERROR - - try { - try { - tryConstructClassFromStringArgs(scriptClass, scriptArgs) - ?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n") - } finally { - // NB: these lines are required (see KT-9546) but aren't covered by tests - System.out.flush() - System.err.flush() - } - } catch (e: Throwable) { - reportExceptionFromScript(e) - return ExitCode.SCRIPT_EXECUTION_ERROR - } - - return ExitCode.OK - } - - private fun repeatAnalysisIfNeeded( - result: AnalysisResult?, - environment: KotlinCoreEnvironment, - targetDescription: String? - ): AnalysisResult? { - if (result is AnalysisResult.RetryWithAdditionalJavaRoots) { - val configuration = environment.configuration - - val oldReadOnlyValue = configuration.isReadOnly - configuration.isReadOnly = false - configuration.addJavaSourceRoots(result.additionalJavaRoots) - configuration.isReadOnly = oldReadOnlyValue - - if (result.addToEnvironment) { - environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) - } - - // Clear package caches (see KotlinJavaPsiFacade) - ApplicationManager.getApplication().runWriteAction { - (PsiManager.getInstance(environment.project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter() - } - - // Clear all diagnostic messages - configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear() - - // Repeat analysis with additional Java roots (kapt generated sources) - return analyze(environment, targetDescription) - } - - return result - } - - private fun reportExceptionFromScript(exception: Throwable) { - // expecting InvocationTargetException from constructor invocation with cause that describes the actual cause - val stream = System.err - val cause = exception.cause - if (exception !is InvocationTargetException || cause == null) { - exception.printStackTrace(stream) - return - } - stream.println(cause) - val fullTrace = cause.stackTrace - for (i in 0 until fullTrace.size - exception.stackTrace.size) { - stream.println("\tat " + fullTrace[i]) - } - } - - fun compileScript(environment: KotlinCoreEnvironment, parentClassLoader: ClassLoader? = null): Class<*>? { - val state = analyzeAndGenerate(environment) ?: return null - - try { - val urls = environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS).mapNotNull { root -> - when (root) { - is JvmModulePathRoot -> root.file // TODO: only add required modules - is JvmClasspathRoot -> root.file - else -> null - } - }.map { it.toURI().toURL() } - - val classLoader = GeneratedClassLoader(state.factory, parentClassLoader ?: URLClassLoader(urls.toTypedArray(), null)) - - val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") - return classLoader.loadClass(script.fqName.asString()) - } catch (e: Exception) { - throw RuntimeException("Failed to evaluate script: $e", e) - } - } - - private fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { - val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null - - if (!result.shouldGenerateCode) return null - - result.throwIfError() - - return generate(environment, environment.configuration, result, environment.getSourceFiles(), null) - } - - private fun analyze(environment: KotlinCoreEnvironment, targetDescription: String?): AnalysisResult? { - val sourceFiles = environment.getSourceFiles() - val collector = environment.messageCollector - - // Can be null for Scripts/REPL - val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) - performanceManager?.notifyAnalysisStarted() - - val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings) - analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { - val project = environment.project - val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNullTo(hashSetOf()) { module -> - environment.findLocalFile(module.getOutputDirectory()) - }.orEmpty() - val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - // To support partial and incremental compilation, we add the scope which contains binaries from output directories - // of the compiled modules (.class) to the list of scopes of the source module - val scope = if (moduleOutputs.isEmpty()) sourcesOnly else sourcesOnly.uniteWith(DirectoriesScope(project, moduleOutputs)) - TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - project, - sourceFiles, - NoScopeRecordCliBindingTrace(), - environment.configuration, - environment::createPackagePartProvider, - sourceModuleSearchScope = scope - ) - } - - performanceManager?.notifyAnalysisFinished(sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription) - - val analysisResult = analyzerWithCompilerReport.analysisResult - - return if (!analyzerWithCompilerReport.hasErrors() || analysisResult is AnalysisResult.RetryWithAdditionalJavaRoots) - analysisResult - else - null - } - - class DirectoriesScope( - project: Project, - private val directories: Set - ) : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { - private val fileSystems = directories.mapTo(hashSetOf(), VirtualFile::getFileSystem) - - override fun contains(file: VirtualFile): Boolean { - if (file.fileSystem !in fileSystems) return false - - var parent: VirtualFile = file - while (true) { - if (parent in directories) return true - parent = parent.parent ?: return false - } - } - - override fun toString() = "All files under: $directories" - } - - private fun GenerationState.Builder.withModule(module: Module?) = - apply { - targetId(module?.let { TargetId(it) }) - moduleName(module?.getModuleName()) - outDirectory(module?.let { File(it.getOutputDirectory()) }) - } - - private fun generate( - environment: KotlinCoreEnvironment, - configuration: CompilerConfiguration, - result: AnalysisResult, - sourceFiles: List, - module: Module? - ): GenerationState { - val generationState = GenerationState.Builder( - environment.project, - ClassBuilderFactories.BINARIES, - result.moduleDescriptor, - result.bindingContext, - sourceFiles, - configuration - ) - .codegenFactory(if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory else DefaultCodegenFactory) - .withModule(module) - .onIndependentPartCompilationEnd(createOutputFilesFlushingCallbackIfPossible(configuration)) - .build() - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) - performanceManager?.notifyGenerationStarted() - - KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - - performanceManager?.notifyGenerationFinished( - sourceFiles.size, - environment.countLinesOfCode(sourceFiles), - additionalDescription = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" - ) - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - AnalyzerWithCompilerReport.reportDiagnostics( - FilteredJvmDiagnostics( - generationState.collectedExtraJvmDiagnostics, - result.bindingContext.diagnostics - ), - environment.messageCollector - ) - - AnalyzerWithCompilerReport.reportBytecodeVersionErrors( - generationState.extraJvmDiagnosticsTrace.bindingContext, environment.messageCollector - ) - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - return generationState - } - - private val KotlinCoreEnvironment.messageCollector: MessageCollector - get() = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) -} diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 deleted file mode 100644 index 543a088f8c2..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt.as32 +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiManager -import com.intellij.psi.impl.PsiModificationTrackerImpl -import com.intellij.psi.search.DelegatingGlobalSearchScope -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics -import org.jetbrains.kotlin.backend.common.output.OutputFileCollection -import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection -import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage -import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil -import org.jetbrains.kotlin.cli.common.output.writeAll -import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback -import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil -import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.javac.JavacWrapper -import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager -import org.jetbrains.kotlin.modules.Module -import org.jetbrains.kotlin.modules.TargetId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs -import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize -import java.io.File -import java.lang.reflect.InvocationTargetException -import java.net.URLClassLoader - -object KotlinToJVMBytecodeCompiler { - - private fun getAbsolutePaths(buildFile: File, module: Module): List { - return module.getSourceFiles().map { sourceFile -> - val source = File(sourceFile) - if (!source.isAbsolute) { - File(buildFile.absoluteFile.parentFile, sourceFile).absolutePath - } else { - source.absolutePath - } - } - } - - private fun writeOutput( - configuration: CompilerConfiguration, - outputFiles: OutputFileCollection, - mainClass: FqName? - ) { - val reportOutputFiles = configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES) - val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR) - val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) - if (jarPath != null) { - val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false) - CompileEnvironmentUtil.writeToJar(jarPath, includeRuntime, mainClass, outputFiles) - if (reportOutputFiles) { - val message = OutputMessageUtil.formatOutputMessage(outputFiles.asList().flatMap { it.sourceFiles }.distinct(), jarPath) - messageCollector.report(OUTPUT, message) - } - return - } - - val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".") - outputFiles.writeAll(outputDir, messageCollector, reportOutputFiles) - } - - private fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback { - if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) { - return GenerationStateEventCallback.DO_NOTHING - } - return GenerationStateEventCallback { state -> - val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput) - writeOutput(configuration, currentOutput, mainClass = null) - if (!configuration.get(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false)) { - state.factory.releaseGeneratedOutput() - } - } - } - - internal fun compileModules(environment: KotlinCoreEnvironment, buildFile: File, chunk: List): Boolean { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) - - val projectConfiguration = environment.configuration - for (module in chunk) { - moduleVisibilityManager.addModule(module) - } - - val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) - for (path in friendPaths) { - moduleVisibilityManager.addFriendPath(path) - } - - val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]" - - val result = repeatAnalysisIfNeeded(analyze(environment, targetDescription), environment, targetDescription) - if (result == null || !result.shouldGenerateCode) return false - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - result.throwIfError() - - val outputs = newLinkedHashMapWithExpectedSize(chunk.size) - - for (module in chunk) { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - val moduleSourcePaths = getAbsolutePaths(buildFile, module) - val ktFiles = environment.getSourceFiles().filter { file -> file.virtualFilePath in moduleSourcePaths } - - if (!checkKotlinPackageUsage(environment, ktFiles)) return false - - val moduleConfiguration = projectConfiguration.copy().apply { - put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory())) - } - - outputs[module] = generate(environment, moduleConfiguration, result, ktFiles, module) - } - - try { - for ((_, state) in outputs) { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - writeOutput(state.configuration, state.factory, null) - } - - if (projectConfiguration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)) { - val singleModule = chunk.singleOrNull() - if (singleModule != null) { - return JavacWrapper.getInstance(environment.project).use { - it.compile(File(singleModule.getOutputDirectory())) - } - } else { - projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( - WARNING, - "A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " + - "-Xuse-javac option couldn't be used to compile java files" - ) - JavacWrapper.getInstance(environment.project).close() - } - } - - return true - } finally { - outputs.values.forEach(GenerationState::destroy) - } - } - - internal fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List, buildFile: File) { - for (module in chunk) { - configuration.addKotlinSourceRoots(getAbsolutePaths(buildFile, module)) - } - - for (module in chunk) { - for ((path, packagePrefix) in module.getJavaSourceRoots()) { - configuration.addJavaSourceRoot(File(path), packagePrefix) - } - } - - val isJava9Module = false /*chunk.any { module -> - module.getJavaSourceRoots().any { (path, packagePrefix) -> - val file = File(path) - packagePrefix == null && - (file.name == PsiJavaModule.MODULE_INFO_FILE || - (file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE })) - } - }*/ - - for (module in chunk) { - for (classpathRoot in module.getClasspathRoots()) { - configuration.add( - CLIConfigurationKeys.CONTENT_ROOTS, - if (isJava9Module) JvmModulePathRoot(File(classpathRoot)) else JvmClasspathRoot(File(classpathRoot)) - ) - } - } - - for (module in chunk) { - val modularJdkRoot = module.modularJdkRoot - if (modularJdkRoot != null) { - // We use the SDK of the first module in the chunk, which is not always correct because some other module in the chunk - // might depend on a different SDK - configuration.put(JVMConfigurationKeys.JDK_HOME, File(modularJdkRoot)) - break - } - } - - configuration.addAll(JVMConfigurationKeys.MODULES, chunk) - } - - private fun findMainClass(generationState: GenerationState, files: List): FqName? { - val mainFunctionDetector = MainFunctionDetector(generationState.bindingContext) - return files.asSequence() - .map { file -> - if (mainFunctionDetector.hasMain(file.declarations)) - JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName - else - null - } - .singleOrNull { it != null } - } - - fun compileBunchOfSources(environment: KotlinCoreEnvironment): Boolean { - val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) - - val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) - for (path in friendPaths) { - moduleVisibilityManager.addFriendPath(path) - } - - if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false - - val generationState = analyzeAndGenerate(environment) ?: return false - - val mainClass = findMainClass(generationState, environment.getSourceFiles()) - - try { - writeOutput(environment.configuration, generationState.factory, mainClass) - return true - } finally { - generationState.destroy() - } - } - - internal fun compileAndExecuteScript(environment: KotlinCoreEnvironment, scriptArgs: List): ExitCode { - val scriptClass = compileScript(environment) ?: return ExitCode.COMPILATION_ERROR - - try { - try { - tryConstructClassFromStringArgs(scriptClass, scriptArgs) - ?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n") - } finally { - // NB: these lines are required (see KT-9546) but aren't covered by tests - System.out.flush() - System.err.flush() - } - } catch (e: Throwable) { - reportExceptionFromScript(e) - return ExitCode.SCRIPT_EXECUTION_ERROR - } - - return ExitCode.OK - } - - private fun repeatAnalysisIfNeeded( - result: AnalysisResult?, - environment: KotlinCoreEnvironment, - targetDescription: String? - ): AnalysisResult? { - if (result is AnalysisResult.RetryWithAdditionalJavaRoots) { - val configuration = environment.configuration - - val oldReadOnlyValue = configuration.isReadOnly - configuration.isReadOnly = false - configuration.addJavaSourceRoots(result.additionalJavaRoots) - configuration.isReadOnly = oldReadOnlyValue - - if (result.addToEnvironment) { - environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) - } - - // Clear package caches (see KotlinJavaPsiFacade) - ApplicationManager.getApplication().runWriteAction { - (PsiManager.getInstance(environment.project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter() - } - - // Clear all diagnostic messages - configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear() - - // Repeat analysis with additional Java roots (kapt generated sources) - return analyze(environment, targetDescription) - } - - return result - } - - private fun reportExceptionFromScript(exception: Throwable) { - // expecting InvocationTargetException from constructor invocation with cause that describes the actual cause - val stream = System.err - val cause = exception.cause - if (exception !is InvocationTargetException || cause == null) { - exception.printStackTrace(stream) - return - } - stream.println(cause) - val fullTrace = cause.stackTrace - for (i in 0 until fullTrace.size - exception.stackTrace.size) { - stream.println("\tat " + fullTrace[i]) - } - } - - fun compileScript(environment: KotlinCoreEnvironment, parentClassLoader: ClassLoader? = null): Class<*>? { - val state = analyzeAndGenerate(environment) ?: return null - - try { - val urls = environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS).mapNotNull { root -> - when (root) { - is JvmModulePathRoot -> root.file // TODO: only add required modules - is JvmClasspathRoot -> root.file - else -> null - } - }.map { it.toURI().toURL() } - - val classLoader = GeneratedClassLoader(state.factory, parentClassLoader ?: URLClassLoader(urls.toTypedArray(), null)) - - val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") - return classLoader.loadClass(script.fqName.asString()) - } catch (e: Exception) { - throw RuntimeException("Failed to evaluate script: $e", e) - } - } - - private fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { - val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null - - if (!result.shouldGenerateCode) return null - - result.throwIfError() - - return generate(environment, environment.configuration, result, environment.getSourceFiles(), null) - } - - private fun analyze(environment: KotlinCoreEnvironment, targetDescription: String?): AnalysisResult? { - val sourceFiles = environment.getSourceFiles() - val collector = environment.messageCollector - - // Can be null for Scripts/REPL - val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) - performanceManager?.notifyAnalysisStarted() - - val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector, environment.configuration.languageVersionSettings) - analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { - val project = environment.project - val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNullTo(hashSetOf()) { module -> - environment.findLocalFile(module.getOutputDirectory()) - }.orEmpty() - val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - // To support partial and incremental compilation, we add the scope which contains binaries from output directories - // of the compiled modules (.class) to the list of scopes of the source module - val scope = if (moduleOutputs.isEmpty()) sourcesOnly else sourcesOnly.uniteWith(DirectoriesScope(project, moduleOutputs)) - TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - project, - sourceFiles, - NoScopeRecordCliBindingTrace(), - environment.configuration, - environment::createPackagePartProvider, - sourceModuleSearchScope = scope - ) - } - - performanceManager?.notifyAnalysisFinished(sourceFiles.size, environment.countLinesOfCode(sourceFiles), targetDescription) - - val analysisResult = analyzerWithCompilerReport.analysisResult - - return if (!analyzerWithCompilerReport.hasErrors() || analysisResult is AnalysisResult.RetryWithAdditionalJavaRoots) - analysisResult - else - null - } - - class DirectoriesScope( - project: Project, - private val directories: Set - ) : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { - private val fileSystems = directories.mapTo(hashSetOf(), VirtualFile::getFileSystem) - - override fun contains(file: VirtualFile): Boolean { - if (file.fileSystem !in fileSystems) return false - - var parent: VirtualFile = file - while (true) { - if (parent in directories) return true - parent = parent.parent ?: return false - } - } - - override fun toString() = "All files under: $directories" - } - - private fun GenerationState.Builder.withModule(module: Module?) = - apply { - targetId(module?.let { TargetId(it) }) - moduleName(module?.getModuleName()) - outDirectory(module?.let { File(it.getOutputDirectory()) }) - } - - private fun generate( - environment: KotlinCoreEnvironment, - configuration: CompilerConfiguration, - result: AnalysisResult, - sourceFiles: List, - module: Module? - ): GenerationState { - val generationState = GenerationState.Builder( - environment.project, - ClassBuilderFactories.BINARIES, - result.moduleDescriptor, - result.bindingContext, - sourceFiles, - configuration - ) - .codegenFactory(if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory else DefaultCodegenFactory) - .withModule(module) - .onIndependentPartCompilationEnd(createOutputFilesFlushingCallbackIfPossible(configuration)) - .build() - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) - performanceManager?.notifyGenerationStarted() - - KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - - performanceManager?.notifyGenerationFinished( - sourceFiles.size, - environment.countLinesOfCode(sourceFiles), - additionalDescription = if (module != null) "target " + module.getModuleName() + "-" + module.getModuleType() + " " else "" - ) - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - AnalyzerWithCompilerReport.reportDiagnostics( - FilteredJvmDiagnostics( - generationState.collectedExtraJvmDiagnostics, - result.bindingContext.diagnostics - ), - environment.messageCollector - ) - - AnalyzerWithCompilerReport.reportBytecodeVersionErrors( - generationState.extraJvmDiagnosticsTrace.bindingContext, environment.messageCollector - ) - - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - return generationState - } - - private val KotlinCoreEnvironment.messageCollector: MessageCollector - get() = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) -} diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as31 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as31 deleted file mode 100644 index b31dbaeaff0..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as31 +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.modules - -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder - -class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder { - private val modulesRoot = jrtFileSystemRoot?.findChild("modules") - private val userModules = linkedMapOf() - - fun addUserModule(module: JavaModule) { - userModules.putIfAbsent(module.name, module) - } - - val allObservableModules: Sequence - get() = systemModules + userModules.values - - val systemModules: Sequence - get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule) - - override fun findModule(name: String): JavaModule? = - modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name] - - private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? { - /* - val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null - val moduleInfo = JavaModuleInfo.read(file) ?: return null - return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file) - */ - return null - } -} diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32 deleted file mode 100644 index b31dbaeaff0..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/CliJavaModuleFinder.kt.as32 +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm.modules - -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule -import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleFinder - -class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder { - private val modulesRoot = jrtFileSystemRoot?.findChild("modules") - private val userModules = linkedMapOf() - - fun addUserModule(module: JavaModule) { - userModules.putIfAbsent(module.name, module) - } - - val allObservableModules: Sequence - get() = systemModules + userModules.values - - val systemModules: Sequence - get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule) - - override fun findModule(name: String): JavaModule? = - modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name] - - private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? { - /* - val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null - val moduleInfo = JavaModuleInfo.read(file) ?: return null - return JavaModule.Explicit(moduleInfo, listOf(JavaModule.Root(moduleRoot, isBinary = true)), file) - */ - return null - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as31 b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as31 deleted file mode 100644 index 1bd0dfffc2d..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as31 +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.resolve.jvm.modules - -import com.intellij.openapi.vfs.VirtualFile -//import com.intellij.psi.PsiJavaModule -import com.intellij.psi.PsiModifier -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.utils.compact -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.ClassVisitor -//import org.jetbrains.org.objectweb.asm.ModuleVisitor -import org.jetbrains.org.objectweb.asm.Opcodes -//import org.jetbrains.org.objectweb.asm.Opcodes.ACC_TRANSITIVE -import java.io.IOException - -class JavaModuleInfo( - val moduleName: String, - val requires: List, - val exports: List -) { - data class Requires(val moduleName: String, val isTransitive: Boolean) - - data class Exports(val packageFqName: FqName, val toModules: List) - - override fun toString(): String = - "Module $moduleName (${requires.size} requires, ${exports.size} exports)" - - companion object { - /*fun create(psiJavaModule: PsiJavaModule): JavaModuleInfo { - return JavaModuleInfo( - psiJavaModule.name, - psiJavaModule.requires.mapNotNull { statement -> - statement.moduleName?.let { moduleName -> - JavaModuleInfo.Requires(moduleName, statement.hasModifierProperty(PsiModifier.TRANSITIVE)) - } - }, - psiJavaModule.exports.mapNotNull { statement -> - statement.packageName?.let { packageName -> - JavaModuleInfo.Exports(FqName(packageName), statement.moduleNames) - } - } - ) - }*/ - - /*fun read(file: VirtualFile): JavaModuleInfo? { - val contents = try { file.contentsToByteArray() } catch (e: IOException) { return null } - - var moduleName: String? = null - val requires = arrayListOf() - val exports = arrayListOf() - - ClassReader(contents).accept(object : ClassVisitor(Opcodes.ASM6) { - override fun visitModule(name: String, access: Int, version: String?): ModuleVisitor { - moduleName = name - - return object : ModuleVisitor(Opcodes.ASM6) { - override fun visitRequire(module: String, access: Int, version: String?) { - requires.add(Requires(module, (access and ACC_TRANSITIVE) != 0)) - } - - override fun visitExport(packageFqName: String, access: Int, modules: Array?) { - // For some reason, '/' is the delimiter in packageFqName here - exports.add(Exports(FqName(packageFqName.replace('/', '.')), modules?.toList().orEmpty())) - } - } - } - }, ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES) - - return if (moduleName != null) - JavaModuleInfo(moduleName!!, requires.compact(), exports.compact()) - else null - }*/ - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32 b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32 deleted file mode 100644 index 1bd0dfffc2d..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/modules/JavaModuleInfo.kt.as32 +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.resolve.jvm.modules - -import com.intellij.openapi.vfs.VirtualFile -//import com.intellij.psi.PsiJavaModule -import com.intellij.psi.PsiModifier -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.utils.compact -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.ClassVisitor -//import org.jetbrains.org.objectweb.asm.ModuleVisitor -import org.jetbrains.org.objectweb.asm.Opcodes -//import org.jetbrains.org.objectweb.asm.Opcodes.ACC_TRANSITIVE -import java.io.IOException - -class JavaModuleInfo( - val moduleName: String, - val requires: List, - val exports: List -) { - data class Requires(val moduleName: String, val isTransitive: Boolean) - - data class Exports(val packageFqName: FqName, val toModules: List) - - override fun toString(): String = - "Module $moduleName (${requires.size} requires, ${exports.size} exports)" - - companion object { - /*fun create(psiJavaModule: PsiJavaModule): JavaModuleInfo { - return JavaModuleInfo( - psiJavaModule.name, - psiJavaModule.requires.mapNotNull { statement -> - statement.moduleName?.let { moduleName -> - JavaModuleInfo.Requires(moduleName, statement.hasModifierProperty(PsiModifier.TRANSITIVE)) - } - }, - psiJavaModule.exports.mapNotNull { statement -> - statement.packageName?.let { packageName -> - JavaModuleInfo.Exports(FqName(packageName), statement.moduleNames) - } - } - ) - }*/ - - /*fun read(file: VirtualFile): JavaModuleInfo? { - val contents = try { file.contentsToByteArray() } catch (e: IOException) { return null } - - var moduleName: String? = null - val requires = arrayListOf() - val exports = arrayListOf() - - ClassReader(contents).accept(object : ClassVisitor(Opcodes.ASM6) { - override fun visitModule(name: String, access: Int, version: String?): ModuleVisitor { - moduleName = name - - return object : ModuleVisitor(Opcodes.ASM6) { - override fun visitRequire(module: String, access: Int, version: String?) { - requires.add(Requires(module, (access and ACC_TRANSITIVE) != 0)) - } - - override fun visitExport(packageFqName: String, access: Int, modules: Array?) { - // For some reason, '/' is the delimiter in packageFqName here - exports.add(Exports(FqName(packageFqName.replace('/', '.')), modules?.toList().orEmpty())) - } - } - } - }, ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES) - - return if (moduleName != null) - JavaModuleInfo(moduleName!!, requires.compact(), exports.compact()) - else null - }*/ - } -}