Reformat module 'cli', fix warnings/inspections

This commit is contained in:
Alexander Udalov
2018-07-26 18:28:18 +02:00
parent 21a7561271
commit 2d875a9cb4
77 changed files with 848 additions and 935 deletions
@@ -17,15 +17,17 @@
package org.jetbrains.kotlin.cli.common package org.jetbrains.kotlin.cli.common
import org.fusesource.jansi.AnsiConsole import org.fusesource.jansi.AnsiConsole
import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
import org.jetbrains.kotlin.cli.common.arguments.ManualLanguageFeatureSetting
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.cli.common.arguments.validateArguments
import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException
import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature.Kind.BUG_FIX
import org.jetbrains.kotlin.config.LanguageFeature.Kind.* import org.jetbrains.kotlin.config.LanguageFeature.State.ENABLED
import org.jetbrains.kotlin.config.LanguageFeature.State.*
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import java.io.PrintStream import java.io.PrintStream
import java.net.URL import java.net.URL
@@ -196,13 +198,11 @@ abstract class CLITool<A : CommonToolArguments> {
} }
@JvmStatic @JvmStatic
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode { fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode = try {
try { compiler.exec(System.err, *args)
return compiler.exec(System.err, *args)
} catch (e: CompileEnvironmentException) { } catch (e: CompileEnvironmentException) {
System.err.println(e.message) System.err.println(e.message)
return ExitCode.INTERNAL_ERROR ExitCode.INTERNAL_ERROR
}
} }
} }
} }
@@ -11,6 +11,7 @@ import java.lang.management.ManagementFactory
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
abstract class CommonCompilerPerformanceManager(private val presentableName: String) { abstract class CommonCompilerPerformanceManager(private val presentableName: String) {
@Suppress("MemberVisibilityCanBePrivate")
protected val measurements: MutableList<PerformanceMeasurement> = mutableListOf() protected val measurements: MutableList<PerformanceMeasurement> = mutableListOf()
protected var isEnabled: Boolean = false protected var isEnabled: Boolean = false
private var initStartNanos = PerformanceCounter.currentTime() private var initStartNanos = PerformanceCounter.currentTime()
@@ -50,13 +50,19 @@ class AnalyzerWithCompilerReport(
val bindingContext = analysisResult.bindingContext val bindingContext = analysisResult.bindingContext
val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY) val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY)
if (!classes.isEmpty()) { if (!classes.isEmpty()) {
val message = StringBuilder("Supertypes of the following classes cannot be resolved. " + val message = StringBuilder(
"Please make sure you have the required dependencies in the classpath:\n") "Supertypes of the following classes cannot be resolved. " +
"Please make sure you have the required dependencies in the classpath:\n"
)
for (descriptor in classes) { for (descriptor in classes) {
val fqName = DescriptorUtils.getFqName(descriptor).asString() val fqName = DescriptorUtils.getFqName(descriptor).asString()
val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor) val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor)
assert(unresolved != null && !unresolved.isEmpty()) { "Incomplete hierarchy should be reported with names of unresolved superclasses: " + fqName } assert(unresolved != null && !unresolved.isEmpty()) {
message.append(" class ").append(fqName).append(", unresolved supertypes: ").append(unresolved!!.joinToString()).append("\n") "Incomplete hierarchy should be reported with names of unresolved superclasses: $fqName"
}
message.append(" class ").append(fqName)
.append(", unresolved supertypes: ").append(unresolved!!.joinToString())
.append("\n")
} }
messageCollector.report(ERROR, message.toString()) messageCollector.report(ERROR, message.toString())
} }
@@ -110,8 +116,9 @@ class AnalyzerWithCompilerReport(
reportAlternativeSignatureErrors() reportAlternativeSignatureErrors()
} }
private class MyDiagnostic<E : PsiElement>(psiElement: E, factory: DiagnosticFactory0<E>, private class MyDiagnostic<E : PsiElement>(
val message: String) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) { psiElement: E, factory: DiagnosticFactory0<E>, val message: String
) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
override fun isValid(): Boolean = true override fun isValid(): Boolean = true
} }
@@ -122,7 +129,7 @@ class AnalyzerWithCompilerReport(
Severity.INFO -> INFO Severity.INFO -> INFO
Severity.ERROR -> ERROR Severity.ERROR -> ERROR
Severity.WARNING -> WARNING Severity.WARNING -> WARNING
else -> throw IllegalStateException("Unknown severity: " + severity) else -> throw IllegalStateException("Unknown severity: $severity")
} }
private val SYNTAX_ERROR_FACTORY = DiagnosticFactory0.create<PsiErrorElement>(Severity.ERROR) private val SYNTAX_ERROR_FACTORY = DiagnosticFactory0.create<PsiErrorElement>(Severity.ERROR)
@@ -192,8 +199,10 @@ class AnalyzerWithCompilerReport(
override fun visitErrorElement(element: PsiErrorElement) { override fun visitErrorElement(element: PsiErrorElement) {
val description = element.errorDescription val description = element.errorDescription
reportDiagnostic(element, SYNTAX_ERROR_FACTORY, reportDiagnostic(
if (StringUtil.isEmpty(description)) "Syntax error" else description) element, SYNTAX_ERROR_FACTORY,
if (StringUtil.isEmpty(description)) "Syntax error" else description
)
} }
} }
@@ -218,7 +227,7 @@ class AnalyzerWithCompilerReport(
for (location in locations) { for (location in locations) {
val data = bindingContext.get(IncompatibleClassTrackerImpl.BYTECODE_VERSION_ERRORS, location) val data = bindingContext.get(IncompatibleClassTrackerImpl.BYTECODE_VERSION_ERRORS, location)
?: error("Value is missing for key in binding context: " + location) ?: error("Value is missing for key in binding context: $location")
reportIncompatibleBinaryVersion(messageCollector, data, severity) reportIncompatibleBinaryVersion(messageCollector, data, severity)
} }
} }
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
interface MessageCollectorBasedReporter : DiagnosticMessageReporter { interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report( override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
@@ -29,15 +29,13 @@ import org.jetbrains.kotlin.util.ModuleVisibilityHelper
import java.io.File import java.io.File
class ModuleVisibilityHelperImpl : ModuleVisibilityHelper { class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
override fun isInFriendModule(what: DeclarationDescriptor, from: DeclarationDescriptor): Boolean { override fun isInFriendModule(what: DeclarationDescriptor, from: DeclarationDescriptor): Boolean {
val fromSource = getSourceElement(from) val fromSource = getSourceElement(from)
// We should check accessibility of 'from' in current module (some set of source files, which are compiled together), // We should check accessibility of 'from' in current module (some set of source files, which are compiled together),
// so we can assume that 'from' should have sources or is a LazyPackageDescriptor with some package files. // so we can assume that 'from' should have sources or is a LazyPackageDescriptor with some package files.
val project: Project = if (fromSource is KotlinSourceElement) { val project: Project = if (fromSource is KotlinSourceElement) {
fromSource.psi.project fromSource.psi.project
} } else {
else {
(from as? LazyPackageDescriptor)?.declarationProvider?.getPackageFiles()?.firstOrNull()?.project ?: return true (from as? LazyPackageDescriptor)?.declarationProvider?.getPackageFiles()?.firstOrNull()?.project ?: return true
} }
@@ -70,8 +68,7 @@ class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
val sourceElement = getSourceElement(descriptor) val sourceElement = getSourceElement(descriptor)
return if (sourceElement is KotlinSourceElement) { return if (sourceElement is KotlinSourceElement) {
modules.singleOrNull() ?: modules.firstOrNull { sourceElement.psi.containingKtFile.virtualFile.path in it.getSourceFiles() } modules.singleOrNull() ?: modules.firstOrNull { sourceElement.psi.containingKtFile.virtualFile.path in it.getSourceFiles() }
} } else {
else {
modules.firstOrNull { module -> modules.firstOrNull { module ->
isContainedByCompiledPartOfOurModule(descriptor, File(module.getOutputDirectory())) || isContainedByCompiledPartOfOurModule(descriptor, File(module.getOutputDirectory())) ||
module.getFriendPaths().any { isContainedByCompiledPartOfOurModule(descriptor, File(it)) } module.getFriendPaths().any { isContainedByCompiledPartOfOurModule(descriptor, File(it)) }
@@ -86,7 +83,7 @@ class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
*/ */
class CliModuleVisibilityManagerImpl(override val enabled: Boolean) : ModuleVisibilityManager, Disposable { class CliModuleVisibilityManagerImpl(override val enabled: Boolean) : ModuleVisibilityManager, Disposable {
override val chunk: MutableList<Module> = arrayListOf() override val chunk: MutableList<Module> = arrayListOf()
override val friendPaths: MutableList <String> = arrayListOf() override val friendPaths: MutableList<String> = arrayListOf()
override fun addModule(module: Module) { override fun addModule(module: Module) {
chunk.add(module) chunk.add(module)
@@ -27,10 +27,7 @@ import kotlin.concurrent.read
import kotlin.concurrent.write import kotlin.concurrent.write
import kotlin.script.experimental.dependencies.ScriptDependencies import kotlin.script.experimental.dependencies.ScriptDependencies
class CliScriptDependenciesProvider( class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
private val project: Project
) : ScriptDependenciesProvider {
private val cacheLock = ReentrantReadWriteLock() private val cacheLock = ReentrantReadWriteLock()
private val cache = hashMapOf<String, ScriptDependencies?>() private val cache = hashMapOf<String, ScriptDependencies?>()
private val scriptContentLoader = ScriptContentLoader(project) private val scriptContentLoader = ScriptContentLoader(project)
@@ -59,8 +56,7 @@ class CliScriptDependenciesProvider(
cache.put(path, deps) cache.put(path, deps)
} }
deps deps
} } else null
else null
} }
} }
} }
@@ -36,7 +36,7 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
return CompilerMessageLocation.create(scriptFile.path, position.startLine, position.startColumn, null) return CompilerMessageLocation.create(scriptFile.path, position.startLine, position.startColumn, null)
} }
private fun ScriptReport.Severity.convertSeverity(): CompilerMessageSeverity = when(this) { private fun ScriptReport.Severity.convertSeverity(): CompilerMessageSeverity = when (this) {
ScriptReport.Severity.FATAL -> CompilerMessageSeverity.ERROR ScriptReport.Severity.FATAL -> CompilerMessageSeverity.ERROR
ScriptReport.Severity.ERROR -> CompilerMessageSeverity.ERROR ScriptReport.Severity.ERROR -> CompilerMessageSeverity.ERROR
ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING
@@ -44,4 +44,3 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
ScriptReport.Severity.DEBUG -> CompilerMessageSeverity.LOGGING ScriptReport.Severity.DEBUG -> CompilerMessageSeverity.LOGGING
} }
} }
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageUtil import org.jetbrains.kotlin.cli.common.messages.MessageUtil
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf import org.jetbrains.kotlin.name.isSubpackageOf
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -30,15 +29,16 @@ fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collectio
return true return true
} }
val messageCollector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) val messageCollector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val kotlinPackage = FqName.topLevel(Name.identifier("kotlin")) val kotlinPackage = FqName("kotlin")
files.forEach { for (file in files) {
if (it.packageFqName.isSubpackageOf(kotlinPackage)) { if (file.packageFqName.isSubpackageOf(kotlinPackage)) {
messageCollector.report(CompilerMessageSeverity.ERROR, messageCollector.report(
CompilerMessageSeverity.ERROR,
"Only the Kotlin standard library is allowed to use the 'kotlin' package", "Only the Kotlin standard library is allowed to use the 'kotlin' package",
MessageUtil.psiElementToMessageLocation(it.packageDirective!!)) MessageUtil.psiElementToMessageLocation(file.packageDirective!!)
)
return false return false
} }
} }
return true return true
} }
@@ -24,7 +24,6 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ExceptionUtil; import com.intellij.util.ExceptionUtil;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import com.intellij.util.containers.HashMap;
import kotlin.collections.ArraysKt; import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt; import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -106,7 +105,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
} }
@NotNull @NotNull
protected TranslationResult translate( private static TranslationResult translate(
@NotNull JsConfig.Reporter reporter, @NotNull JsConfig.Reporter reporter,
@NotNull List<KtFile> allKotlinFiles, @NotNull List<KtFile> allKotlinFiles,
@NotNull JsAnalysisResult jsAnalysisResult, @NotNull JsAnalysisResult jsAnalysisResult,
@@ -116,7 +115,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
K2JSTranslator translator = new K2JSTranslator(config); K2JSTranslator translator = new K2JSTranslator(config);
IncrementalDataProvider incrementalDataProvider = config.getConfiguration().get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER); IncrementalDataProvider incrementalDataProvider = config.getConfiguration().get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER);
if (incrementalDataProvider != null) { if (incrementalDataProvider != null) {
Map<File, KtFile> nonCompiledSources = new HashMap<File, KtFile>(allKotlinFiles.size()); Map<File, KtFile> nonCompiledSources = new HashMap<>(allKotlinFiles.size());
for (KtFile ktFile : allKotlinFiles) { for (KtFile ktFile : allKotlinFiles) {
nonCompiledSources.put(VfsUtilCore.virtualToIoFile(ktFile.getVirtualFile()), ktFile); nonCompiledSources.put(VfsUtilCore.virtualToIoFile(ktFile.getVirtualFile()), ktFile);
} }
@@ -169,7 +168,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
return COMPILATION_ERROR; return COMPILATION_ERROR;
} }
ExitCode pluginLoadResult = PluginCliParser.loadPluginsSafe(arguments.getPluginClasspaths(), arguments.getPluginOptions(), configuration); ExitCode pluginLoadResult =
PluginCliParser.loadPluginsSafe(arguments.getPluginClasspaths(), arguments.getPluginOptions(), configuration);
if (pluginLoadResult != ExitCode.OK) return pluginLoadResult; if (pluginLoadResult != ExitCode.OK) return pluginLoadResult;
configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector)); configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector));
@@ -20,11 +20,9 @@ import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
object BundledCompilerPlugins { object BundledCompilerPlugins {
val componentRegistrars: List<ComponentRegistrar> val componentRegistrars: List<ComponentRegistrar>
get() = emptyList() get() = emptyList()
val commandLineProcessors: List<CommandLineProcessor> val commandLineProcessors: List<CommandLineProcessor>
get() = emptyList() get() = emptyList()
} }
@@ -64,8 +64,7 @@ object JvmRuntimeVersionsConsistencyChecker {
JvmRuntimeVersionsConsistencyChecker::class.java JvmRuntimeVersionsConsistencyChecker::class.java
.getResourceAsStream("/kotlinManifest.properties") .getResourceAsStream("/kotlinManifest.properties")
.let { input -> Properties().apply { load(input) } } .let { input -> Properties().apply { load(input) } }
} } catch (e: Exception) {
catch (e: Exception) {
LOG.error(e) LOG.error(e)
throw e throw e
} }
@@ -141,14 +140,15 @@ object JvmRuntimeVersionsConsistencyChecker {
override val apiVersion: ApiVersion get() = actualApi override val apiVersion: ApiVersion get() = actualApi
} }
messageCollector.issue(null, "Old runtime has been found in the classpath. " + messageCollector.issue(
null, "Old runtime has been found in the classpath. " +
"Initial language version settings: $languageVersionSettings. " + "Initial language version settings: $languageVersionSettings. " +
"Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING) "Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING
)
configuration.languageVersionSettings = newSettings configuration.languageVersionSettings = newSettings
} }
} } else if (consistency != ClasspathConsistency.Consistent) {
else if (consistency != ClasspathConsistency.Consistent) {
messageCollector.issue( messageCollector.issue(
null, null,
"Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath" "Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath"
@@ -185,6 +185,7 @@ object JvmRuntimeVersionsConsistencyChecker {
val actualRuntimeVersion: MavenComparableVersion, val actualRuntimeVersion: MavenComparableVersion,
val incompatibleJars: List<KotlinLibraryFile> val incompatibleJars: List<KotlinLibraryFile>
) : ClasspathConsistency() ) : ClasspathConsistency()
object InconsistentWithCompilerVersion : ClasspathConsistency() object InconsistentWithCompilerVersion : ClasspathConsistency()
object InconsistentBecauseOfRuntimesWithDifferentVersions : ClasspathConsistency() object InconsistentBecauseOfRuntimesWithDifferentVersions : ClasspathConsistency()
} }
@@ -330,8 +331,7 @@ object JvmRuntimeVersionsConsistencyChecker {
val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF) val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF)
val manifest = try { val manifest = try {
manifestFile?.let { Manifest(it.inputStream) } manifestFile?.let { Manifest(it.inputStream) }
} } catch (e: IOException) {
catch (e: IOException) {
return FileKind.Irrelevant return FileKind.Irrelevant
} }
@@ -243,7 +243,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
val jars = arrayOf( val jars = arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR, KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_JAR,
KOTLIN_SCRIPTING_JVM_JAR, KOTLIN_SCRIPTING_MISC_JAR KOTLIN_SCRIPTING_JVM_JAR, KOTLIN_SCRIPTING_MISC_JAR
).mapNotNull { File(libPath, it).takeIf { it.exists() }?.canonicalPath } ).mapNotNull { File(libPath, it).takeIf(File::exists)?.canonicalPath }
if (jars.size == 4) { if (jars.size == 4) {
pluginClasspaths = jars + pluginClasspaths pluginClasspaths = jars + pluginClasspaths
} }
@@ -308,19 +308,19 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments, services: Services configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments, services: Services
) { ) {
if (IncrementalCompilation.isEnabledForJvm()) { if (IncrementalCompilation.isEnabledForJvm()) {
services.get(LookupTracker::class.java)?.let { services[LookupTracker::class.java]?.let {
configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, it) configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, it)
} }
services.get(ExpectActualTracker::class.java)?.let { services[ExpectActualTracker::class.java]?.let {
configuration.put(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, it) configuration.put(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER, it)
} }
services.get(IncrementalCompilationComponents::class.java)?.let { services[IncrementalCompilationComponents::class.java]?.let {
configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, it) configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, it)
} }
services.get(JavaClassesTracker::class.java)?.let { services[JavaClassesTracker::class.java]?.let {
configuration.put(JVMConfigurationKeys.JAVA_CLASSES_TRACKER, it) configuration.put(JVMConfigurationKeys.JAVA_CLASSES_TRACKER, it)
} }
} }
@@ -93,8 +93,7 @@ class ClasspathRootsResolver(
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath) val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) { if (modularRoot != null) {
modules += modularRoot modules += modularRoot
} } else {
else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix -> result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix) if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also { else null.also {
@@ -190,8 +189,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF") val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try { return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
} } catch (e: IOException) {
catch (e: IOException) {
null null
} }
} }
@@ -211,16 +209,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name) val existing = javaModuleFinder.findModule(module.name)
if (existing == null) { if (existing == null) {
javaModuleFinder.addUserModule(module) javaModuleFinder.addUserModule(module)
} } else if (module.moduleRoots != existing.moduleRoots) {
else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() = fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it } moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile() val thisFile = module.getRootFile()
val existingFile = existing.getRootFile() val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}" 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}' " + report(
"has been found earlier on the module path$atExistingPath", thisFile) 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
)
} }
} }
@@ -257,8 +256,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName) val module = javaModuleFinder.findModule(moduleName)
if (module == null) { if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph") report(ERROR, "Module $moduleName cannot be found in the module graph")
} } else {
else {
for ((root, isBinary) in module.moduleRoots) { for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE)) result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
} }
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiJavaModule
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule import com.intellij.psi.impl.light.LightJavaModule
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -94,8 +93,7 @@ class ClasspathRootsResolver(
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath) val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) { if (modularRoot != null) {
modules += modularRoot modules += modularRoot
} } else {
else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix -> result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix) if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also { else null.also {
@@ -127,7 +125,7 @@ class ClasspathRootsResolver(
return RootsAndModules(result, modules) return RootsAndModules(result, modules)
} }
/* /*
private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? { private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? {
val moduleInfoFile = val moduleInfoFile =
when { when {
@@ -198,8 +196,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF") val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try { return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
} } catch (e: IOException) {
catch (e: IOException) {
null null
} }
} }
@@ -219,16 +216,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name) val existing = javaModuleFinder.findModule(module.name)
if (existing == null) { if (existing == null) {
javaModuleFinder.addUserModule(module) javaModuleFinder.addUserModule(module)
} } else if (module.moduleRoots != existing.moduleRoots) {
else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() = fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it } moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile() val thisFile = module.getRootFile()
val existingFile = existing.getRootFile() val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}" 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}' " + report(
"has been found earlier on the module path$atExistingPath", thisFile) 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
)
} }
} }
@@ -265,8 +263,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName) val module = javaModuleFinder.findModule(moduleName)
if (module == null) { if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph") report(ERROR, "Module $moduleName cannot be found in the module graph")
} } else {
else {
for ((root, isBinary) in module.moduleRoots) { for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE)) result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
} }
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiJavaModule
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule import com.intellij.psi.impl.light.LightJavaModule
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -94,8 +93,7 @@ class ClasspathRootsResolver(
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath) val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) { if (modularRoot != null) {
modules += modularRoot modules += modularRoot
} } else {
else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix -> result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix) if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also { else null.also {
@@ -127,7 +125,7 @@ class ClasspathRootsResolver(
return RootsAndModules(result, modules) return RootsAndModules(result, modules)
} }
/* /*
private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? { private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? {
val moduleInfoFile = val moduleInfoFile =
when { when {
@@ -198,8 +196,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF") val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try { return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
} } catch (e: IOException) {
catch (e: IOException) {
null null
} }
} }
@@ -219,16 +216,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name) val existing = javaModuleFinder.findModule(module.name)
if (existing == null) { if (existing == null) {
javaModuleFinder.addUserModule(module) javaModuleFinder.addUserModule(module)
} } else if (module.moduleRoots != existing.moduleRoots) {
else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() = fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it } moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile() val thisFile = module.getRootFile()
val existingFile = existing.getRootFile() val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}" 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}' " + report(
"has been found earlier on the module path$atExistingPath", thisFile) 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
)
} }
} }
@@ -265,8 +263,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName) val module = javaModuleFinder.findModule(moduleName)
if (module == null) { if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph") report(ERROR, "Module $moduleName cannot be found in the module graph")
} } else {
else {
for ((root, isBinary) in module.moduleRoots) { for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE)) result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
} }
@@ -10,15 +10,12 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchScopeUtil import com.intellij.psi.search.PsiSearchScopeUtil
import com.intellij.util.Function
import com.intellij.util.SmartList import com.intellij.util.SmartList
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer
@@ -35,19 +32,14 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
class CliKotlinAsJavaSupport( class CliKotlinAsJavaSupport(
project: Project, project: Project,
private val traceHolder: CliTraceHolder private val traceHolder: CliTraceHolder
): KotlinAsJavaSupport() { ) : KotlinAsJavaSupport() {
private val psiManager = PsiManager.getInstance(project) private val psiManager = PsiManager.getInstance(project)
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> { override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
return findFacadeFilesInPackage(packageFqName, scope) return findFacadeFilesInPackage(packageFqName, scope)
.groupBy { it.javaFileFacadeFqName } .groupBy { it.javaFileFacadeFqName }
.mapNotNull { .mapNotNull { (facadeClassFqName, files) ->
KtLightClassForFacade.createForFacade( KtLightClassForFacade.createForFacade(psiManager, facadeClassFqName, scope, files)
psiManager,
it.key,
scope,
it.value
)
} }
} }
@@ -67,13 +59,8 @@ class CliKotlinAsJavaSupport(
val filesForFacade = findFilesForFacade(facadeFqName, scope) val filesForFacade = findFilesForFacade(facadeFqName, scope)
if (filesForFacade.isEmpty()) return emptyList() if (filesForFacade.isEmpty()) return emptyList()
return listOfNotNull<PsiClass>( return listOfNotNull(
KtLightClassForFacade.createForFacade( KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade)
psiManager,
facadeFqName,
scope,
filesForFacade
)
) )
} }
@@ -88,7 +75,6 @@ class CliKotlinAsJavaSupport(
} }
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> { override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
//
return emptyList() return emptyList()
} }
@@ -97,7 +83,7 @@ class CliKotlinAsJavaSupport(
return traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_FQ_NAME, facadeFqName)?.filter { return traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_FQ_NAME, facadeFqName)?.filter {
PsiSearchScopeUtil.isInScope(scope, it) PsiSearchScopeUtil.isInScope(scope, it)
} ?: emptyList() }.orEmpty()
} }
@@ -122,20 +108,10 @@ class CliKotlinAsJavaSupport(
override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName> { override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName> {
val packageView = traceHolder.module.getPackage(fqn) val packageView = traceHolder.module.getPackage(fqn)
val members = packageView.memberScope.getContributedDescriptors( return packageView.memberScope.getContributedDescriptors(
DescriptorKindFilter.PACKAGES, DescriptorKindFilter.PACKAGES,
MemberScope.ALL_NAME_FILTER MemberScope.ALL_NAME_FILTER
) ).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName }
return ContainerUtil.mapNotNull(
members,
object : Function<DeclarationDescriptor, FqName> {
override fun `fun`(member: DeclarationDescriptor): FqName? {
if (member is PackageViewDescriptor) {
return member.fqName
}
return null
}
})
} }
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? =
@@ -144,24 +120,18 @@ class CliKotlinAsJavaSupport(
override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = override fun getLightClassForScript(script: KtScript): KtLightClassForScript? =
KtLightClassForScript.create(script) KtLightClassForScript.create(script)
override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> { override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> {
return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull { return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull {
val element = DescriptorToSourceUtils.getSourceFromDescriptor(it) val element = DescriptorToSourceUtils.getSourceFromDescriptor(it)
if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope( if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) {
searchScope,
element element
) } else null
) {
element
}
else null
} }
} }
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> { override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> {
return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter { return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter {
PsiSearchScopeUtil.isInScope(searchScope, it) PsiSearchScopeUtil.isInScope(searchScope, it)
} ?: emptyList() }.orEmpty()
} }
} }
@@ -39,9 +39,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses * To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
*/ */
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() { class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
override fun createDataHolderForClass( override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
classOrObject: KtClassOrObject, builder: LightClassBuilder
): LightClassDataHolder.ForClass {
//force resolve companion for light class generation //force resolve companion for light class generation
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
@@ -49,10 +47,7 @@ class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) :
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassDataHolder bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassDataHolder
return LightClassDataHolderImpl( return LightClassDataHolderImpl(stub, diagnostics)
stub,
diagnostics
)
} }
override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade { override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade {
@@ -75,5 +70,3 @@ class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) :
override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext
} }
@@ -45,7 +45,7 @@ class CliTraceHolder : CodeAnalyzerInitializer {
// TODO: needs better name + list of keys to skip somewhere // TODO: needs better name + list of keys to skip somewhere
class NoScopeRecordCliBindingTrace : CliBindingTrace() { class NoScopeRecordCliBindingTrace : CliBindingTrace() {
override fun <K, V> record(slice: WritableSlice<K, V>, key: K, value: V) { override fun <K, V> record(slice: WritableSlice<K, V>, key: K, value: V) {
if (slice === BindingContext.LEXICAL_SCOPE || slice == BindingContext.DATA_FLOW_INFO_BEFORE) { if (slice == BindingContext.LEXICAL_SCOPE || slice == BindingContext.DATA_FLOW_INFO_BEFORE) {
// In the compiler there's no need to keep scopes // In the compiler there's no need to keep scopes
return return
} }
@@ -38,7 +38,10 @@ class CliVirtualFileFinder(
override fun findMetadata(classId: ClassId): InputStream? { override fun findMetadata(classId: ClassId): InputStream? {
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" } assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream return findBinaryClass(
classId,
classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION
)?.inputStream
} }
override fun hasMetadataPackage(fqName: FqName): Boolean { override fun hasMetadataPackage(fqName: FqName): Boolean {
@@ -21,10 +21,6 @@ public class CompileEnvironmentException extends RuntimeException {
super(message); super(message);
} }
public CompileEnvironmentException(Throwable cause) {
super(cause);
}
public CompileEnvironmentException(String message, Throwable cause) { public CompileEnvironmentException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
@@ -73,7 +73,9 @@ public class CompileEnvironmentUtil {
} }
// TODO: includeRuntime should be not a flag but a path to runtime // TODO: includeRuntime should be not a flag but a path to runtime
private static void doWriteToJar(OutputFileCollection outputFiles, OutputStream fos, @Nullable FqName mainClass, boolean includeRuntime) { private static void doWriteToJar(
OutputFileCollection outputFiles, OutputStream fos, @Nullable FqName mainClass, boolean includeRuntime
) {
try { try {
Manifest manifest = new Manifest(); Manifest manifest = new Manifest();
Attributes mainAttributes = manifest.getMainAttributes(); Attributes mainAttributes = manifest.getMainAttributes();
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type -> index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type) findVirtualFileGivenPackage(dir, relativeClassName, type)
} } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope } }?.takeIf { it in searchScope }
} }
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap() private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = private val signatureParsingComponent = BinaryClassSignatureParser()
BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? { override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) } val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass( BinaryJavaClass(
virtualFile, virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
classId.asSingleFqName(), outerClass = null, classContent = classContent
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
) )
} }
} }
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile return vFile
} }
private fun VirtualFile.findPsiClassInVirtualFile( private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
classNameWithInnerClasses: String
): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file) return findClassInPsiFile(classNameWithInnerClasses, file)
} }
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> { override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>() val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
dir, _ ->
for (child in dir.children) { for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") { if (child.extension == "class" || child.extension == "java") {
result.add(child.nameWithoutExtension) result.add(child.nameWithoutExtension)
@@ -286,15 +276,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
} }
// a sad workaround to avoid throwing exception when called from inside IDEA code // a sad workaround to avoid throwing exception when called from inside IDEA code
private fun <T : Any> safely(compute: () -> T): T? = try { private fun <T : Any> safely(compute: () -> T): T? =
try {
compute() compute()
} } catch (e: IllegalArgumentException) {
catch (e: IllegalArgumentException) {
null null
} } catch (e: AssertionError) {
catch (e: AssertionError) {
null null
} }
private fun String.toSafeFqName(): FqName? = safely { FqName(this) } private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type -> index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type) findVirtualFileGivenPackage(dir, relativeClassName, type)
} } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope } }?.takeIf { it in searchScope }
} }
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap() private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = private val signatureParsingComponent = BinaryClassSignatureParser()
BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? { override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) } val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass( BinaryJavaClass(
virtualFile, virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
classId.asSingleFqName(), outerClass = null, classContent = classContent
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
) )
} }
} }
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile return vFile
} }
private fun VirtualFile.findPsiClassInVirtualFile( private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
classNameWithInnerClasses: String
): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file) return findClassInPsiFile(classNameWithInnerClasses, file)
} }
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> { override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>() val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
dir, _ ->
for (child in dir.children) { for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") { if (child.extension == "class" || child.extension == "java") {
result.add(child.nameWithoutExtension) result.add(child.nameWithoutExtension)
@@ -288,15 +278,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
} }
// a sad workaround to avoid throwing exception when called from inside IDEA code // a sad workaround to avoid throwing exception when called from inside IDEA code
private fun <T : Any> safely(compute: () -> T): T? = try { private fun <T : Any> safely(compute: () -> T): T? =
try {
compute() compute()
} } catch (e: IllegalArgumentException) {
catch (e: IllegalArgumentException) {
null null
} } catch (e: AssertionError) {
catch (e: AssertionError) {
null null
} }
private fun String.toSafeFqName(): FqName? = safely { FqName(this) } private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type -> index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type) findVirtualFileGivenPackage(dir, relativeClassName, type)
} } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope } }?.takeIf { it in searchScope }
} }
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap() private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = private val signatureParsingComponent = BinaryClassSignatureParser()
BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? { override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) } val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass( BinaryJavaClass(
virtualFile, virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
classId.asSingleFqName(), outerClass = null, classContent = classContent
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
) )
} }
} }
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile return vFile
} }
private fun VirtualFile.findPsiClassInVirtualFile( private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
classNameWithInnerClasses: String
): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file) return findClassInPsiFile(classNameWithInnerClasses, file)
} }
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> { override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>() val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
dir, _ ->
for (child in dir.children) { for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") { if (child.extension == "class" || child.extension == "java") {
result.add(child.nameWithoutExtension) result.add(child.nameWithoutExtension)
@@ -288,15 +278,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
} }
// a sad workaround to avoid throwing exception when called from inside IDEA code // a sad workaround to avoid throwing exception when called from inside IDEA code
private fun <T : Any> safely(compute: () -> T): T? = try { private fun <T : Any> safely(compute: () -> T): T? =
try {
compute() compute()
} } catch (e: IllegalArgumentException) {
catch (e: IllegalArgumentException) {
null null
} } catch (e: AssertionError) {
catch (e: AssertionError) {
null null
} }
private fun String.toSafeFqName(): FqName? = safely { FqName(this) } private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -20,7 +20,6 @@ import com.intellij.core.JavaCoreApplicationEnvironment
import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.controlFlow.ControlFlowFactory
open class KotlinCoreProjectEnvironment( open class KotlinCoreProjectEnvironment(
disposable: Disposable, disposable: Disposable,
@@ -29,7 +29,9 @@ import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.* 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.messages.AnalyzerWithCompilerReport 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.OUTPUT
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
@@ -51,12 +53,10 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File import java.io.File
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler { object KotlinToJVMBytecodeCompiler {
@@ -159,12 +159,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory())) it.compile(File(singleModule.getOutputDirectory()))
} }
} else { } else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let { projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
it.report(
WARNING, WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files" "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() JavacWrapper.getInstance(environment.project).close()
} }
} }
@@ -335,11 +334,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString()) return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) { } catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e) throw RuntimeException("Failed to evaluate script: $e", e)
} }
} }
fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { private fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? {
val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null
if (!result.shouldGenerateCode) return null if (!result.shouldGenerateCode) return null
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -53,12 +52,10 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File import java.io.File
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler { object KotlinToJVMBytecodeCompiler {
@@ -161,12 +158,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory())) it.compile(File(singleModule.getOutputDirectory()))
} }
} else { } else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let { projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
it.report(
WARNING, WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files" "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() JavacWrapper.getInstance(environment.project).close()
} }
} }
@@ -337,11 +333,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString()) return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) { } catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e) throw RuntimeException("Failed to evaluate script: $e", e)
} }
} }
fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { private fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? {
val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null
if (!result.shouldGenerateCode) return null if (!result.shouldGenerateCode) return null
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -53,12 +52,10 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File import java.io.File
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler { object KotlinToJVMBytecodeCompiler {
@@ -161,12 +158,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory())) it.compile(File(singleModule.getOutputDirectory()))
} }
} else { } else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let { projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
it.report(
WARNING, WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files" "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() JavacWrapper.getInstance(environment.project).close()
} }
} }
@@ -337,11 +333,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString()) return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) { } catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e) throw RuntimeException("Failed to evaluate script: $e", e)
} }
} }
fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { private fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? {
val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null val result = repeatAnalysisIfNeeded(analyze(environment, null), environment, null) ?: return null
if (!result.shouldGenerateCode) return null if (!result.shouldGenerateCode) return null
@@ -30,7 +30,12 @@ class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
override fun findExternalAnnotation(listOwner: PsiModifierListOwner, annotationFQN: String): PsiAnnotation? = null override fun findExternalAnnotation(listOwner: PsiModifierListOwner, annotationFQN: String): PsiAnnotation? = null
override fun findExternalAnnotations(listOwner: PsiModifierListOwner): Array<out PsiAnnotation>? = null override fun findExternalAnnotations(listOwner: PsiModifierListOwner): Array<out PsiAnnotation>? = null
override fun annotateExternally(listOwner: PsiModifierListOwner, annotationFQName: String, fromFile: PsiFile, value: Array<out PsiNameValuePair>?) { override fun annotateExternally(
listOwner: PsiModifierListOwner,
annotationFQName: String,
fromFile: PsiFile,
value: Array<out PsiNameValuePair>?
) {
throw UnsupportedOperationException("not implemented") throw UnsupportedOperationException("not implemented")
} }
@@ -38,7 +43,11 @@ class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
throw UnsupportedOperationException("not implemented") throw UnsupportedOperationException("not implemented")
} }
override fun editExternalAnnotation(listOwner: PsiModifierListOwner, annotationFQN: String, value: Array<out PsiNameValuePair>?): Boolean { override fun editExternalAnnotation(
listOwner: PsiModifierListOwner,
annotationFQN: String,
value: Array<out PsiNameValuePair>?
): Boolean {
throw UnsupportedOperationException("not implemented") throw UnsupportedOperationException("not implemented")
} }
@@ -1,31 +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;
public class ModuleExecutionException extends RuntimeException {
public ModuleExecutionException(String message) {
super(message);
}
public ModuleExecutionException(Throwable cause) {
super(cause);
}
public ModuleExecutionException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -50,7 +50,6 @@ import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
@@ -66,7 +65,6 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import java.util.* import java.util.*
import kotlin.reflect.KFunction1 import kotlin.reflect.KFunction1
@@ -150,8 +148,7 @@ object TopDownAnalyzerFacadeForJVM {
if (createBuiltInsFromModule) if (createBuiltInsFromModule)
JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule
else module.builtIns.builtInsModule else module.builtIns.builtInsModule
} } else null
else null
fun StorageComponentContainer.useJavac() { fun StorageComponentContainer.useJavac() {
useImpl<JavacBasedClassFinder>() useImpl<JavacBasedClassFinder>()
@@ -159,6 +156,7 @@ object TopDownAnalyzerFacadeForJVM {
useImpl<JavacBasedSourceElementFactory>() useImpl<JavacBasedSourceElementFactory>()
} }
@Suppress("USELESS_CAST")
val configureJavaClassFinder = val configureJavaClassFinder =
if (configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) StorageComponentContainer::useJavac if (configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) StorageComponentContainer::useJavac
else null as KFunction1<StorageComponentContainer, Unit>? else null as KFunction1<StorageComponentContainer, Unit>?
@@ -177,16 +175,19 @@ object TopDownAnalyzerFacadeForJVM {
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder
) )
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get<JavaDescriptorResolver>() moduleClassResolver.compiledCodeResolver = dependenciesContainer.get()
dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule)) dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule))
dependenciesContext.initializeModuleContents(CompositePackageFragmentProvider(listOf( dependenciesContext.initializeModuleContents(
CompositePackageFragmentProvider(
listOf(
moduleClassResolver.compiledCodeResolver.packageFragmentProvider, moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>() dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>()
))) )
)
)
dependenciesContext.module dependenciesContext.module
} } else null
else null
val partProvider = packagePartProvider(sourceScope).let { fragment -> val partProvider = packagePartProvider(sourceScope).let { fragment ->
if (targetIds == null || incrementalComponents == null) fragment if (targetIds == null || incrementalComponents == null) fragment
@@ -203,18 +204,17 @@ object TopDownAnalyzerFacadeForJVM {
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER] javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
).apply { ).apply {
initJvmBuiltInsForTopDownAnalysis() initJvmBuiltInsForTopDownAnalysis()
(partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get<DeserializationConfiguration>() (partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get()
} }
moduleClassResolver.sourceCodeResolver = container.get<JavaDescriptorResolver>() moduleClassResolver.sourceCodeResolver = container.get()
val additionalProviders = ArrayList<PackageFragmentProvider>() val additionalProviders = ArrayList<PackageFragmentProvider>()
if (incrementalComponents != null) { if (incrementalComponents != null) {
targetIds?.mapTo(additionalProviders) { targetId -> targetIds?.mapTo(additionalProviders) { targetId ->
IncrementalPackageFragmentProvider( IncrementalPackageFragmentProvider(
files, module, storageManager, container.get<DeserializationComponentsForJava>().components, files, module, storageManager, container.get<DeserializationComponentsForJava>().components,
incrementalComponents.getIncrementalCache(targetId), targetId, incrementalComponents.getIncrementalCache(targetId), targetId, container.get()
container.get<KotlinClassFinder>()
) )
} }
} }
@@ -231,10 +231,11 @@ object TopDownAnalyzerFacadeForJVM {
listOfNotNull(module, dependencyModule, optionalBuiltInsModule), listOfNotNull(module, dependencyModule, optionalBuiltInsModule),
if (dependencyModule != null) setOf(dependencyModule) else emptySet() if (dependencyModule != null) setOf(dependencyModule) else emptySet()
) )
module.initialize(CompositePackageFragmentProvider( module.initialize(
listOf(container.get<KotlinCodeAnalyzer>().packageFragmentProvider) + CompositePackageFragmentProvider(
additionalProviders listOf(container.get<KotlinCodeAnalyzer>().packageFragmentProvider) + additionalProviders
)) )
)
return container return container
} }
@@ -58,7 +58,7 @@ fun CompilerConfiguration.addJavaSourceRoots(files: List<File>, packagePrefix: S
} }
val CompilerConfiguration.javaSourceRoots: Set<String> val CompilerConfiguration.javaSourceRoots: Set<String>
get() = getList(JVMConfigurationKeys.CONTENT_ROOTS).mapNotNullTo(linkedSetOf<String>()) { root -> get() = getList(JVMConfigurationKeys.CONTENT_ROOTS).mapNotNullTo(linkedSetOf()) { root ->
when (root) { when (root) {
is KotlinSourceRoot -> root.path is KotlinSourceRoot -> root.path
is JavaSourceRoot -> root.file.path is JavaSourceRoot -> root.file.path
@@ -29,7 +29,7 @@ import java.util.*
// speeds up finding files/classes in classpath/java source roots // speeds up finding files/classes in classpath/java source roots
// NOT THREADSAFE, needs to be adapted/removed if we want compiler to be multithreaded // NOT THREADSAFE, needs to be adapted/removed if we want compiler to be multithreaded
// the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal // the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal
class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex { class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex {
//these fields are computed based on _roots passed to constructor which are filled in later //these fields are computed based on _roots passed to constructor which are filled in later
private val roots: List<JavaRoot> by lazy { _roots.toList() } private val roots: List<JavaRoot> by lazy { _roots.toList() }
@@ -95,16 +95,14 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes
if (limitedRootTypes.isEmpty()) { if (limitedRootTypes.isEmpty()) {
null null
} } else {
else {
search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory) search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory)
} }
} }
is SearchResult.Found -> { is SearchResult.Found -> {
if (cachedRequest.acceptedRootTypes == acceptedRootTypes) { if (cachedRequest.acceptedRootTypes == acceptedRootTypes) {
findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type) findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type)
} } else {
else {
search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory) search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
} }
} }
@@ -184,8 +182,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
if (prefixPathSegments[pathIndex].identifier != subPackageName) { if (prefixPathSegments[pathIndex].identifier != subPackageName) {
return null return null
} }
} } else {
else {
currentFile = currentFile.findChildPackage(subPackageName, pathRoot.type) ?: return null currentFile = currentFile.findChildPackage(subPackageName, pathRoot.type) ?: return null
} }
@@ -39,10 +39,12 @@ class JavacLogger(
companion object { companion object {
fun preRegister(context: Context, messageCollector: MessageCollector) { fun preRegister(context: Context, messageCollector: MessageCollector) {
context.put(Log.logKey, Context.Factory<Log> { context.put(Log.logKey, Context.Factory<Log> {
JavacLogger(it, JavacLogger(
it,
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)), PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)), PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO))) PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO))
)
}) })
} }
} }
@@ -38,7 +38,8 @@ class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: Li
return supersCache[classOrObject]!! return supersCache[classOrObject]!!
} }
val classDescriptor = lightClassGenerationSupport.analyze(classOrObject).get(BindingContext.CLASS, classOrObject) ?: return emptyList() val classDescriptor =
lightClassGenerationSupport.analyze(classOrObject).get(BindingContext.CLASS, classOrObject) ?: return emptyList()
val classIds = classDescriptor.defaultType.constructor.supertypes val classIds = classDescriptor.defaultType.constructor.supertypes
.mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.classId } .mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.classId }
supersCache[classOrObject] = classIds supersCache[classOrObject] = classIds
@@ -49,12 +50,12 @@ class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: Li
override fun findField(classOrObject: KtClassOrObject, name: String): JavaField? { override fun findField(classOrObject: KtClassOrObject, name: String): JavaField? {
val lightClass = classOrObject.toLightClass() ?: return null val lightClass = classOrObject.toLightClass() ?: return null
return lightClass.allFields.find { it.name == name}?.let(::MockKotlinField) return lightClass.allFields.find { it.name == name }?.let(::MockKotlinField)
} }
override fun findField(ktFile: KtFile?, name: String): JavaField? { override fun findField(ktFile: KtFile?, name: String): JavaField? {
val lightClass = ktFile?.findFacadeClass() ?: return null val lightClass = ktFile?.findFacadeClass() ?: return null
return lightClass.allFields.find { it.name == name}?.let(::MockKotlinField) return lightClass.allFields.find { it.name == name }?.let(::MockKotlinField)
} }
} }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.psi.KtFile
import java.io.File import java.io.File
object JavacWrapperRegistrar { object JavacWrapperRegistrar {
private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context" private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context"
fun registerJavac( fun registerJavac(
@@ -46,8 +45,7 @@ object JavacWrapperRegistrar {
try { try {
Class.forName(JAVAC_CONTEXT_CLASS) Class.forName(JAVAC_CONTEXT_CLASS)
} } catch (e: ClassNotFoundException) {
catch (e: ClassNotFoundException) {
messageCollector.report(ERROR, "'$JAVAC_CONTEXT_CLASS' class can't be found ('tools.jar' is not found)") messageCollector.report(ERROR, "'$JAVAC_CONTEXT_CLASS' class can't be found ('tools.jar' is not found)")
return false return false
} }
@@ -60,8 +58,10 @@ object JavacWrapperRegistrar {
val compileJava = configuration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA) val compileJava = configuration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)
val kotlinSupertypesResolver = JavacWrapperKotlinResolverImpl(lightClassGenerationSupport) val kotlinSupertypesResolver = JavacWrapperKotlinResolverImpl(lightClassGenerationSupport)
val javacWrapper = JavacWrapper(javaFiles, kotlinFiles, arguments, jvmClasspathRoots, bootClasspath, sourcePath, val javacWrapper = JavacWrapper(
kotlinSupertypesResolver, compileJava, outputDirectory, context) javaFiles, kotlinFiles, arguments, jvmClasspathRoots, bootClasspath, sourcePath,
kotlinSupertypesResolver, compileJava, outputDirectory, context
)
project.registerService(JavacWrapper::class.java, javacWrapper) project.registerService(JavacWrapper::class.java, javacWrapper)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.modules package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem
import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
@@ -55,8 +55,7 @@ internal class CoreJrtVirtualFile(private val handler: CoreJrtHandler, private v
override fun getChildren(): Array<out VirtualFile> { override fun getChildren(): Array<out VirtualFile> {
val paths = try { val paths = try {
Files.newDirectoryStream(path).use(Iterable<Path>::toList) Files.newDirectoryStream(path).use(Iterable<Path>::toList)
} } catch (e: IOException) {
catch (e: IOException) {
emptyList<Path>() emptyList<Path>()
} }
return when { return when {
@@ -26,32 +26,31 @@ import org.jetbrains.kotlin.cli.jvm.BundledCompilerPlugins
import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.compiler.plugin.*
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File import java.io.File
import java.net.URL
import java.util.* import java.util.*
object PluginCliParser { object PluginCliParser {
@JvmStatic @JvmStatic
fun loadPluginsSafe(pluginClasspaths: Array<String>?, pluginOptions: Array<String>?, configuration: CompilerConfiguration): ExitCode = fun loadPluginsSafe(pluginClasspaths: Array<String>?, pluginOptions: Array<String>?, configuration: CompilerConfiguration): ExitCode =
loadPluginsSafe(pluginClasspaths?.asIterable(), pluginOptions?.asIterable(), configuration) loadPluginsSafe(pluginClasspaths?.asIterable(), pluginOptions?.asIterable(), configuration)
@JvmStatic @JvmStatic
fun loadPluginsSafe(pluginClasspaths: Iterable<String>?, pluginOptions: Iterable<String>?, configuration: CompilerConfiguration): ExitCode { fun loadPluginsSafe(
pluginClasspaths: Iterable<String>?,
pluginOptions: Iterable<String>?,
configuration: CompilerConfiguration
): ExitCode {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
try { try {
PluginCliParser.loadPlugins(pluginClasspaths, pluginOptions, configuration) PluginCliParser.loadPlugins(pluginClasspaths, pluginOptions, configuration)
} } catch (e: PluginCliOptionProcessingException) {
catch (e: PluginCliOptionProcessingException) {
val message = e.message + "\n\n" + cliPluginUsageString(e.pluginId, e.options) val message = e.message + "\n\n" + cliPluginUsageString(e.pluginId, e.options)
messageCollector.report(CompilerMessageSeverity.ERROR, message) messageCollector.report(CompilerMessageSeverity.ERROR, message)
return ExitCode.INTERNAL_ERROR return ExitCode.INTERNAL_ERROR
} } catch (e: CliOptionProcessingException) {
catch (e: CliOptionProcessingException) {
messageCollector.report(CompilerMessageSeverity.ERROR, e.message!!) messageCollector.report(CompilerMessageSeverity.ERROR, e.message!!)
return ExitCode.INTERNAL_ERROR return ExitCode.INTERNAL_ERROR
} } catch (t: Throwable) {
catch (t: Throwable) {
MessageCollectorUtil.reportException(messageCollector, t) MessageCollectorUtil.reportException(messageCollector, t)
return ExitCode.INTERNAL_ERROR return ExitCode.INTERNAL_ERROR
} }
@@ -64,7 +63,7 @@ object PluginCliParser {
pluginClasspaths pluginClasspaths
?.map { File(it).toURI().toURL() } ?.map { File(it).toURI().toURL() }
?.toTypedArray() ?.toTypedArray()
?: arrayOf<URL>(), ?: emptyArray(),
this::class.java.classLoader this::class.java.classLoader
) )
@@ -104,13 +103,15 @@ object PluginCliParser {
throw PluginCliOptionProcessingException( throw PluginCliOptionProcessingException(
processor.pluginId, processor.pluginId,
processor.pluginOptions, processor.pluginOptions,
"Required plugin option not present: ${processor.pluginId}:${option.name}") "Required plugin option not present: ${processor.pluginId}:${option.name}"
)
} }
if (!option.allowMultipleOccurrences && values.size > 1) { if (!option.allowMultipleOccurrences && values.size > 1) {
throw PluginCliOptionProcessingException( throw PluginCliOptionProcessingException(
processor.pluginId, processor.pluginId,
processor.pluginOptions, processor.pluginOptions,
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.name}") "Multiple values are not allowed for plugin option ${processor.pluginId}:${option.name}"
)
} }
for (value in values) { for (value in values) {
@@ -27,8 +27,7 @@ internal class PluginURLClassLoader(urls: Array<URL>, parent: ClassLoader) : Cla
override fun loadClass(name: String, resolve: Boolean): Class<*> { override fun loadClass(name: String, resolve: Boolean): Class<*> {
return try { return try {
childClassLoader.findClass(name) childClassLoader.findClass(name)
} } catch (e: ClassNotFoundException) {
catch (e: ClassNotFoundException) {
super.loadClass(name, resolve) super.loadClass(name, resolve)
} }
} }
@@ -45,8 +44,7 @@ internal class PluginURLClassLoader(urls: Array<URL>, parent: ClassLoader) : Cla
return try { return try {
super.findClass(name) super.findClass(name)
} } catch (e: ClassNotFoundException) {
catch (e: ClassNotFoundException) {
onFail.loadClass(name) onFail.loadClass(name)
} }
} }
@@ -31,8 +31,10 @@ open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberD
override fun containsFile(file: KtFile) = delegate.containsFile(file) override fun containsFile(file: KtFile) = delegate.containsFile(file)
override fun getDeclarations(kindFilter: DescriptorKindFilter, override fun getDeclarations(
nameFilter: (Name) -> Boolean) = delegate.getDeclarations(kindFilter, nameFilter) kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
) = delegate.getDeclarations(kindFilter, nameFilter)
override fun getFunctionDeclarations(name: Name) = delegate.getFunctionDeclarations(name) override fun getFunctionDeclarations(name: Name) = delegate.getFunctionDeclarations(name)
@@ -43,26 +43,28 @@ class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : Ba
} }
private fun checkConsistent(removedCompiledLines: Iterable<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) { private fun checkConsistent(removedCompiledLines: Iterable<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) {
removedCompiledLines.zip(removedAnalyzedLines).forEach { removedCompiledLines.zip(removedAnalyzedLines).forEach { (removedCompiledLine, removedAnalyzedLine) ->
if (it.first != LineId(it.second)) { if (removedCompiledLine != LineId(removedAnalyzedLine)) {
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}") throw IllegalStateException("History mismatch when resetting lines: ${removedCompiledLine.no} != $removedAnalyzedLine")
} }
} }
} }
} }
abstract class GenericReplCheckerState: IReplStageState<ScriptDescriptor> { abstract class GenericReplCheckerState : IReplStageState<ScriptDescriptor> {
// "line" - is the unit of evaluation here, could in fact consists of several character lines // "line" - is the unit of evaluation here, could in fact consists of several character lines
class LineState( class LineState(
val codeLine: ReplCodeLine, val codeLine: ReplCodeLine,
val psiFile: KtFile, val psiFile: KtFile,
val errorHolder: DiagnosticMessageHolder) val errorHolder: DiagnosticMessageHolder
)
var lastLineState: LineState? = null // for transferring state to the compiler in most typical case var lastLineState: LineState? = null // for transferring state to the compiler in most typical case
} }
class GenericReplCompilerState(environment: KotlinCoreEnvironment, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) : IReplStageState<ScriptDescriptor>, GenericReplCheckerState() { class GenericReplCompilerState(environment: KotlinCoreEnvironment, override val lock: ReentrantReadWriteLock = ReentrantReadWriteLock()) :
IReplStageState<ScriptDescriptor>, GenericReplCheckerState() {
override val history = ReplCompilerStageHistory(this) override val history = ReplCompilerStageHistory(this)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.repl package org.jetbrains.kotlin.cli.jvm.repl
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.openapi.vfs.CharsetToolkit
@@ -72,7 +71,11 @@ open class GenericReplChecker(
val checkerState = state.asState(GenericReplCheckerState::class.java) val checkerState = state.asState(GenericReplCheckerState::class.java)
val scriptFileName = makeScriptBaseName(codeLine) val scriptFileName = makeScriptBaseName(codeLine)
val virtualFile = val virtualFile =
LightVirtualFile("$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, StringUtil.convertLineSeparators(codeLine.code)).apply { LightVirtualFile(
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
KotlinLanguage.INSTANCE,
StringUtil.convertLineSeparators(codeLine.code)
).apply {
charset = CharsetToolkit.UTF8_CHARSET charset = CharsetToolkit.UTF8_CHARSET
} }
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile? val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.repl package org.jetbrains.kotlin.cli.jvm.repl
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
@@ -24,6 +23,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.repl.* import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -41,14 +41,18 @@ import kotlin.concurrent.write
// WARNING: not thread safe, assuming external synchronization // WARNING: not thread safe, assuming external synchronization
open class GenericReplCompiler(disposable: Disposable, open class GenericReplCompiler(
disposable: Disposable,
scriptDefinition: KotlinScriptDefinition, scriptDefinition: KotlinScriptDefinition,
private val compilerConfiguration: CompilerConfiguration, private val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector messageCollector: MessageCollector
) : ReplCompiler { ) : ReplCompiler {
constructor(scriptDefinition: KotlinScriptDefinition, compilerConfiguration: CompilerConfiguration, messageCollector: MessageCollector) : constructor(
this(Disposer.newDisposable(), scriptDefinition, compilerConfiguration, messageCollector) scriptDefinition: KotlinScriptDefinition,
compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : this(Disposer.newDisposable(), scriptDefinition, compilerConfiguration, messageCollector)
private val checker = GenericReplChecker(disposable, scriptDefinition, compilerConfiguration, messageCollector) private val checker = GenericReplChecker(disposable, scriptDefinition, compilerConfiguration, messageCollector)
@@ -66,7 +70,8 @@ open class GenericReplCompiler(disposable: Disposable,
when (res) { when (res) {
is ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete() is ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete()
is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(res.message, res.location) is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(res.message, res.location)
is ReplCheckResult.Ok -> {} // continue is ReplCheckResult.Ok -> {
} // continue
} }
} }
Pair(compilerState.lastLineState!!.psiFile, compilerState.lastLineState!!.errorHolder) Pair(compilerState.lastLineState!!.psiFile, compilerState.lastLineState!!.errorHolder)
@@ -102,15 +107,14 @@ open class GenericReplCompiler(disposable: Disposable,
generationState, generationState,
psiFile.script!!.containingKtFile.packageFqName, psiFile.script!!.containingKtFile.packageFqName,
setOf(psiFile.script!!.containingKtFile), setOf(psiFile.script!!.containingKtFile),
org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION) CompilationErrorHandler.THROW_EXCEPTION
)
val generatedClassname = makeScriptBaseName(codeLine) val generatedClassname = makeScriptBaseName(codeLine)
compilerState.history.push(LineId(codeLine), scriptDescriptor) compilerState.history.push(LineId(codeLine), scriptDescriptor)
val expression = psiFile.getChildOfType<KtScript>()?. val expression = psiFile.getChildOfType<KtScript>()?.getChildOfType<KtBlockExpression>()?.getChildOfType<KtScriptInitializer>()
getChildOfType<KtBlockExpression>()?. ?.getChildOfType<KtExpression>()
getChildOfType<KtScriptInitializer>()?.
getChildOfType<KtExpression>()
val type = expression?.let { val type = expression?.let {
compilerState.analyzerEngine.trace.bindingContext.getType(it) compilerState.analyzerEngine.trace.bindingContext.getType(it)
@@ -118,17 +122,19 @@ open class GenericReplCompiler(disposable: Disposable,
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)
} }
return ReplCompileResult.CompiledClasses(LineId(codeLine), return ReplCompileResult.CompiledClasses(
LineId(codeLine),
compilerState.history.map { it.id }, compilerState.history.map { it.id },
generatedClassname, generatedClassname,
generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) }, generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
generationState.replSpecific.hasResult, generationState.replSpecific.hasResult,
classpathAddendum ?: emptyList(), classpathAddendum ?: emptyList(),
type) type
)
} }
} }
companion object { companion object {
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result" private const val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
} }
} }
@@ -47,7 +47,6 @@ import org.jetbrains.kotlin.resolve.scopes.utils.replaceImportingScopes
import org.jetbrains.kotlin.script.ScriptPriorities import org.jetbrains.kotlin.script.ScriptPriorities
class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) { class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
private val topDownAnalysisContext: TopDownAnalysisContext private val topDownAnalysisContext: TopDownAnalysisContext
private val topDownAnalyzer: LazyTopDownAnalyzer private val topDownAnalyzer: LazyTopDownAnalyzer
private val resolveSession: ResolveSession private val resolveSession: ResolveSession
@@ -71,20 +70,21 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
{ _, _ -> ScriptMutableDeclarationProviderFactory() } { _, _ -> ScriptMutableDeclarationProviderFactory() }
) )
this.module = container.get<ModuleDescriptorImpl>() this.module = container.get()
this.scriptDeclarationFactory = container.get<ScriptMutableDeclarationProviderFactory>() this.scriptDeclarationFactory = container.get()
this.resolveSession = container.get<ResolveSession>() this.resolveSession = container.get()
this.topDownAnalysisContext = TopDownAnalysisContext( this.topDownAnalysisContext = TopDownAnalysisContext(
TopDownAnalysisMode.TopLevelDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider TopDownAnalysisMode.TopLevelDeclarations, DataFlowInfoFactory.EMPTY, resolveSession.declarationScopeProvider
) )
this.topDownAnalyzer = container.get<LazyTopDownAnalyzer>() this.topDownAnalyzer = container.get()
} }
interface ReplLineAnalysisResult { interface ReplLineAnalysisResult {
val scriptDescriptor: ScriptDescriptor? val scriptDescriptor: ScriptDescriptor?
val diagnostics: Diagnostics val diagnostics: Diagnostics
data class Successful(override val scriptDescriptor: ScriptDescriptor, override val diagnostics: Diagnostics) : ReplLineAnalysisResult data class Successful(override val scriptDescriptor: ScriptDescriptor, override val diagnostics: Diagnostics) :
ReplLineAnalysisResult
data class WithErrors(override val diagnostics: Diagnostics) : ReplLineAnalysisResult { data class WithErrors(override val diagnostics: Diagnostics) : ReplLineAnalysisResult {
override val scriptDescriptor: ScriptDescriptor? get() = null override val scriptDescriptor: ScriptDescriptor? get() = null
@@ -115,8 +115,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
return if (hasErrors) { return if (hasErrors) {
replState.lineFailure(linePsi, codeLine) replState.lineFailure(linePsi, codeLine)
ReplLineAnalysisResult.WithErrors(diagnostics) ReplLineAnalysisResult.WithErrors(diagnostics)
} } else {
else {
val scriptDescriptor = context.scripts[linePsi.script]!! val scriptDescriptor = context.scripts[linePsi.script]!!
replState.lineSuccess(linePsi, codeLine, scriptDescriptor) replState.lineSuccess(linePsi, codeLine, scriptDescriptor)
ReplLineAnalysisResult.Successful(scriptDescriptor, diagnostics) ReplLineAnalysisResult.Successful(scriptDescriptor, diagnostics)
@@ -134,8 +133,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
val provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT)!! val provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT)!!
try { try {
rootPackageProvider.addDelegateProvider(provider) rootPackageProvider.addDelegateProvider(provider)
} } catch (e: UninitializedPropertyAccessException) {
catch (e: UninitializedPropertyAccessException) {
rootPackageProvider = AdaptablePackageMemberDeclarationProvider(provider) rootPackageProvider = AdaptablePackageMemberDeclarationProvider(provider)
} }
} }
@@ -167,8 +165,8 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
} }
} }
// TODO: merge with org.jetbrains.kotlin.resolve.repl.ReplState when switching to new REPL infrastruct everywhere // TODO: merge with org.jetbrains.kotlin.resolve.repl.ReplState when switching to new REPL infrastructure everywhere
// TODO: review it's place in the extracted state infrastruct (now the analyzer itself is a part of the state // TODO: review its place in the extracted state infrastructure (now the analyzer itself is a part of the state)
class ResettableAnalyzerState { class ResettableAnalyzerState {
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>() private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
private val submittedLines = hashMapOf<KtFile, LineInfo>() private val submittedLines = hashMapOf<KtFile, LineInfo>()
@@ -212,7 +210,12 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
abstract val parentLine: SuccessfulLine? abstract val parentLine: SuccessfulLine?
class SubmittedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo() class SubmittedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo()
class SuccessfulLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?, val lineDescriptor: LazyScriptDescriptor) : LineInfo() class SuccessfulLine(
override val linePsi: KtFile,
override val parentLine: SuccessfulLine?,
val lineDescriptor: LazyScriptDescriptor
) : LineInfo()
class FailedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo() class FailedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo()
} }
@@ -22,8 +22,8 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
import org.jetbrains.kotlin.cli.jvm.repl.configuration.ConsoleReplConfiguration import org.jetbrains.kotlin.cli.jvm.repl.configuration.ConsoleReplConfiguration
import org.jetbrains.kotlin.cli.jvm.repl.configuration.ReplConfiguration
import org.jetbrains.kotlin.cli.jvm.repl.configuration.IdeReplConfiguration import org.jetbrains.kotlin.cli.jvm.repl.configuration.IdeReplConfiguration
import org.jetbrains.kotlin.cli.jvm.repl.configuration.ReplConfiguration
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion
@@ -53,9 +53,11 @@ class ReplFromTerminal(
private fun doRun() { private fun doRun() {
try { try {
with (writer) { with(writer) {
printlnWelcomeMessage("Welcome to Kotlin version ${KotlinCompilerVersion.VERSION} " + printlnWelcomeMessage(
"(JRE ${System.getProperty("java.runtime.version")})") "Welcome to Kotlin version ${KotlinCompilerVersion.VERSION} " +
"(JRE ${System.getProperty("java.runtime.version")})"
)
printlnWelcomeMessage("Type :help for help, :quit for quit") printlnWelcomeMessage("Type :help for help, :quit for quit")
} }
@@ -71,16 +73,13 @@ class ReplFromTerminal(
break break
} }
} }
} } catch (e: Exception) {
catch (e: Exception) {
replConfiguration.exceptionReporter.report(e) replConfiguration.exceptionReporter.report(e)
throw e throw e
} } finally {
finally {
try { try {
replConfiguration.commandReader.flushHistory() replConfiguration.commandReader.flushHistory()
} } catch (e: Exception) {
catch (e: Exception) {
replConfiguration.exceptionReporter.report(e) replConfiguration.exceptionReporter.report(e)
throw e throw e
} }
@@ -99,7 +98,7 @@ class ReplFromTerminal(
line = unescapeLineBreaks(line) line = unescapeLineBreaks(line)
if (line.startsWith(":") && (line.length == 1 || line.get(1) != ':')) { if (line.startsWith(":") && (line.length == 1 || line[1] != ':')) {
val notQuit = oneCommand(line.substring(1)) val notQuit = oneCommand(line.substring(1))
return if (notQuit) WhatNextAfterOneLine.READ_LINE else WhatNextAfterOneLine.QUIT return if (notQuit) WhatNextAfterOneLine.READ_LINE else WhatNextAfterOneLine.QUIT
} }
@@ -107,8 +106,7 @@ class ReplFromTerminal(
val lineResult = eval(line) val lineResult = eval(line)
return if (lineResult is ReplEvalResult.Incomplete) { return if (lineResult is ReplEvalResult.Incomplete) {
WhatNextAfterOneLine.INCOMPLETE WhatNextAfterOneLine.INCOMPLETE
} } else {
else {
WhatNextAfterOneLine.READ_LINE WhatNextAfterOneLine.READ_LINE
} }
} }
@@ -132,22 +130,21 @@ class ReplFromTerminal(
@Throws(Exception::class) @Throws(Exception::class)
private fun oneCommand(command: String): Boolean { private fun oneCommand(command: String): Boolean {
val split = splitCommand(command) val split = splitCommand(command)
if (split.size >= 1 && command == "help") { if (split.isNotEmpty() && command == "help") {
writer.printlnHelpMessage("Available commands:\n" + writer.printlnHelpMessage(
"Available commands:\n" +
":help show this help\n" + ":help show this help\n" +
":quit exit the interpreter\n" + ":quit exit the interpreter\n" +
":dump bytecode dump classes to terminal\n" + ":dump bytecode dump classes to terminal\n" +
":load <file> load script from specified file") ":load <file> load script from specified file"
)
return true return true
} } else if (split.size >= 2 && split[0] == "dump" && split[1] == "bytecode") {
else if (split.size >= 2 && split[0] == "dump" && split[1] == "bytecode") {
replInterpreter.dumpClasses(PrintWriter(System.out)) replInterpreter.dumpClasses(PrintWriter(System.out))
return true return true
} } else if (split.isNotEmpty() && split[0] == "quit") {
else if (split.size >= 1 && split[0] == "quit") {
return false return false
} } else if (split.size >= 2 && split[0] == "load") {
else if (split.size >= 2 && split[0] == "load") {
val fileName = split[1] val fileName = split[1]
try { try {
val scriptText = FileUtil.loadFile(File(fileName)) val scriptText = FileUtil.loadFile(File(fileName))
@@ -156,8 +153,7 @@ class ReplFromTerminal(
writer.outputCompileError("Can not load script: ${e.message}") writer.outputCompileError("Can not load script: ${e.message}")
} }
return true return true
} } else {
else {
writer.printlnHelpMessage("Unknown command\n" + "Type :help for help") writer.printlnHelpMessage("Unknown command\n" + "Type :help for help")
return true return true
} }
@@ -173,12 +169,10 @@ class ReplFromTerminal(
val replConfiguration = if (replIdeMode) IdeReplConfiguration() else ConsoleReplConfiguration() val replConfiguration = if (replIdeMode) IdeReplConfiguration() else ConsoleReplConfiguration()
return try { return try {
ReplFromTerminal(disposable, configuration, replConfiguration).doRun() ReplFromTerminal(disposable, configuration, replConfiguration).doRun()
} } catch (e: Exception) {
catch (e: Exception) {
replConfiguration.exceptionReporter.report(e) replConfiguration.exceptionReporter.report(e)
throw e throw e
} }
} }
} }
} }
@@ -60,14 +60,18 @@ class ReplInterpreter(
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
val msg = messageRenderer.render(severity, message, location).trimEnd() val msg = messageRenderer.render(severity, message, location).trimEnd()
with (replConfiguration.writer) { with(replConfiguration.writer) {
when (severity) { when (severity) {
CompilerMessageSeverity.EXCEPTION -> sendInternalErrorReport(msg) CompilerMessageSeverity.EXCEPTION -> sendInternalErrorReport(msg)
CompilerMessageSeverity.ERROR -> outputCompileError(msg) CompilerMessageSeverity.ERROR -> outputCompileError(msg)
CompilerMessageSeverity.STRONG_WARNING -> {} // TODO consider reporting this and two below CompilerMessageSeverity.STRONG_WARNING -> {
CompilerMessageSeverity.WARNING -> {} } // TODO consider reporting this and two below
CompilerMessageSeverity.INFO -> {} CompilerMessageSeverity.WARNING -> {
else -> {} }
CompilerMessageSeverity.INFO -> {
}
else -> {
}
} }
} }
} }
@@ -86,14 +90,17 @@ class ReplInterpreter(
private val evalState by lazy { scriptEvaluator.createState() } private val evalState by lazy { scriptEvaluator.createState() }
fun eval(line: String): ReplEvalResult { fun eval(line: String): ReplEvalResult {
val fullText = (previousIncompleteLines + line).joinToString(separator = "\n") val fullText = (previousIncompleteLines + line).joinToString(separator = "\n")
try { try {
val evalRes = scriptEvaluator.compileAndEval(
val evalRes = scriptEvaluator.compileAndEval(evalState, ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText), null, object : InvokeWrapper { evalState,
ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText),
null,
object : InvokeWrapper {
override fun <T> invoke(body: () -> T): T = replConfiguration.executionInterceptor.execute(body) override fun <T> invoke(body: () -> T): T = replConfiguration.executionInterceptor.execute(body)
}) }
)
when { when {
evalRes !is ReplEvalResult.Incomplete -> previousIncompleteLines.clear() evalRes !is ReplEvalResult.Incomplete -> previousIncompleteLines.clear()
@@ -101,8 +108,7 @@ class ReplInterpreter(
else -> return ReplEvalResult.Error.CompileTime("incomplete code") else -> return ReplEvalResult.Error.CompileTime("incomplete code")
} }
return evalRes return evalRes
} } catch (e: Throwable) {
catch (e: Throwable) {
val writer = PrintWriter(System.err) val writer = PrintWriter(System.err)
classLoader.dumpClasses(writer) classLoader.dumpClasses(writer)
writer.flush() writer.flush()
@@ -28,7 +28,8 @@ class ConsoleDiagnosticMessageHolder : MessageCollectorBasedReporter, Diagnostic
override val messageCollector: GroupingMessageCollector = GroupingMessageCollector( override val messageCollector: GroupingMessageCollector = GroupingMessageCollector(
PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.WITHOUT_PATHS, false), PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.WITHOUT_PATHS, false),
false) false
)
override fun renderMessage(): String { override fun renderMessage(): String {
messageCollector.flush() messageCollector.flush()
@@ -38,16 +38,14 @@ class ConsoleReplCommandReader : ReplCommandReader {
override fun readLine(next: ReplFromTerminal.WhatNextAfterOneLine): String? { override fun readLine(next: ReplFromTerminal.WhatNextAfterOneLine): String? {
val prompt = if (next == ReplFromTerminal.WhatNextAfterOneLine.INCOMPLETE) "... " else ">>> " val prompt = if (next == ReplFromTerminal.WhatNextAfterOneLine.INCOMPLETE) "... " else ">>> "
try { return try {
return lineReader.readLine(prompt) lineReader.readLine(prompt)
} } catch (e: UserInterruptException) {
catch (e: UserInterruptException) {
println("<interrupted>") println("<interrupted>")
System.out.flush() System.out.flush()
return "" ""
} } catch (e: EndOfFileException) {
catch (e: EndOfFileException) { null
return null
} }
} }
@@ -55,7 +53,7 @@ class ConsoleReplCommandReader : ReplCommandReader {
private companion object { private companion object {
init { init {
Logger.getLogger("org.jline").level = Level.OFF; Logger.getLogger("org.jline").level = Level.OFF
} }
} }
} }
@@ -39,7 +39,8 @@ class ReplSystemInWrapper(
private val isAtBufferEnd: Boolean private val isAtBufferEnd: Boolean
get() = curBytePos == inputByteArray.size get() = curBytePos == inputByteArray.size
@Volatile var isReplScriptExecuting = false @Volatile
var isReplScriptExecuting = false
override fun read(): Int { override fun read(): Int {
if (isLastByteProcessed) { if (isLastByteProcessed) {
@@ -74,12 +74,16 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
if (destination != null) { if (destination != null) {
if (destination.endsWith(".jar")) { if (destination.endsWith(".jar")) {
// TODO: support .jar destination // TODO: support .jar destination
collector.report(STRONG_WARNING, ".jar destination is not yet supported, results will be written to the directory with the given name") collector.report(
STRONG_WARNING,
".jar destination is not yet supported, results will be written to the directory with the given name"
)
} }
configuration.put(CLIConfigurationKeys.METADATA_DESTINATION_DIRECTORY, File(destination)) configuration.put(CLIConfigurationKeys.METADATA_DESTINATION_DIRECTORY, File(destination))
} }
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.METADATA_CONFIG_FILES) val environment =
KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.METADATA_CONFIG_FILES)
if (environment.getSourceFiles().isEmpty()) { if (environment.getSourceFiles().isEmpty()) {
if (arguments.version) { if (arguments.version) {
@@ -95,8 +99,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
val metadataVersion = val metadataVersion =
configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? BuiltInsBinaryVersion ?: BuiltInsBinaryVersion.INSTANCE configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? BuiltInsBinaryVersion ?: BuiltInsBinaryVersion.INSTANCE
MetadataSerializer(metadataVersion, true).serialize(environment) MetadataSerializer(metadataVersion, true).serialize(environment)
} } catch (e: CompilationException) {
catch (e: CompilationException) {
collector.report(EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element)) collector.report(EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element))
return ExitCode.INTERNAL_ERROR return ExitCode.INTERNAL_ERROR
} }
@@ -91,18 +91,24 @@ open class MetadataSerializer(
for (declaration in file.declarations) { for (declaration in file.declarations) {
declaration.accept(object : KtVisitorVoid() { declaration.accept(object : KtVisitorVoid() {
override fun visitNamedFunction(function: KtNamedFunction) { override fun visitNamedFunction(function: KtNamedFunction) {
members.add(bindingContext.get(BindingContext.FUNCTION, function) members.add(
?: error("No descriptor found for function ${function.fqName}")) bindingContext.get(BindingContext.FUNCTION, function)
?: error("No descriptor found for function ${function.fqName}")
)
} }
override fun visitProperty(property: KtProperty) { override fun visitProperty(property: KtProperty) {
members.add(bindingContext.get(BindingContext.VARIABLE, property) members.add(
?: error("No descriptor found for property ${property.fqName}")) bindingContext.get(BindingContext.VARIABLE, property)
?: error("No descriptor found for property ${property.fqName}")
)
} }
override fun visitTypeAlias(typeAlias: KtTypeAlias) { override fun visitTypeAlias(typeAlias: KtTypeAlias) {
members.add(bindingContext.get(BindingContext.TYPE_ALIAS, typeAlias) members.add(
?: error("No descriptor found for type alias ${typeAlias.fqName}")) bindingContext.get(BindingContext.TYPE_ALIAS, typeAlias)
?: error("No descriptor found for type alias ${typeAlias.fqName}")
)
} }
override fun visitClassOrObject(classOrObject: KtClassOrObject) { override fun visitClassOrObject(classOrObject: KtClassOrObject) {