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
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.CompilerMessageSeverity.INFO
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.Kind.*
import org.jetbrains.kotlin.config.LanguageFeature.State.*
import org.jetbrains.kotlin.config.LanguageFeature.Kind.BUG_FIX
import org.jetbrains.kotlin.config.LanguageFeature.State.ENABLED
import org.jetbrains.kotlin.config.Services
import java.io.PrintStream
import java.net.URL
@@ -196,13 +198,11 @@ abstract class CLITool<A : CommonToolArguments> {
}
@JvmStatic
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode {
try {
return compiler.exec(System.err, *args)
} catch (e: CompileEnvironmentException) {
System.err.println(e.message)
return ExitCode.INTERNAL_ERROR
}
fun doMainNoExit(compiler: CLITool<*>, args: Array<String>): ExitCode = try {
compiler.exec(System.err, *args)
} catch (e: CompileEnvironmentException) {
System.err.println(e.message)
ExitCode.INTERNAL_ERROR
}
}
}
@@ -11,6 +11,7 @@ import java.lang.management.ManagementFactory
import java.util.concurrent.TimeUnit
abstract class CommonCompilerPerformanceManager(private val presentableName: String) {
@Suppress("MemberVisibilityCanBePrivate")
protected val measurements: MutableList<PerformanceMeasurement> = mutableListOf()
protected var isEnabled: Boolean = false
private var initStartNanos = PerformanceCounter.currentTime()
@@ -86,4 +87,4 @@ abstract class CommonCompilerPerformanceManager(private val presentableName: Str
appendln("$presentableName performance report")
measurements.map { it.render() }.sorted().forEach { appendln(it) }
}.toByteArray()
}
}
@@ -50,13 +50,19 @@ class AnalyzerWithCompilerReport(
val bindingContext = analysisResult.bindingContext
val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY)
if (!classes.isEmpty()) {
val message = StringBuilder("Supertypes of the following classes cannot be resolved. " +
"Please make sure you have the required dependencies in the classpath:\n")
val message = StringBuilder(
"Supertypes of the following classes cannot be resolved. " +
"Please make sure you have the required dependencies in the classpath:\n"
)
for (descriptor in classes) {
val fqName = DescriptorUtils.getFqName(descriptor).asString()
val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor)
assert(unresolved != null && !unresolved.isEmpty()) { "Incomplete hierarchy should be reported with names of unresolved superclasses: " + fqName }
message.append(" class ").append(fqName).append(", unresolved supertypes: ").append(unresolved!!.joinToString()).append("\n")
assert(unresolved != null && !unresolved.isEmpty()) {
"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())
}
@@ -110,8 +116,9 @@ class AnalyzerWithCompilerReport(
reportAlternativeSignatureErrors()
}
private class MyDiagnostic<E : PsiElement>(psiElement: E, factory: DiagnosticFactory0<E>,
val message: String) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
private class MyDiagnostic<E : PsiElement>(
psiElement: E, factory: DiagnosticFactory0<E>, val message: String
) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
override fun isValid(): Boolean = true
}
@@ -122,7 +129,7 @@ class AnalyzerWithCompilerReport(
Severity.INFO -> INFO
Severity.ERROR -> ERROR
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)
@@ -131,9 +138,9 @@ class AnalyzerWithCompilerReport(
if (!diagnostic.isValid) return false
reporter.report(
diagnostic,
diagnostic.psiFile,
(diagnostic as? MyDiagnostic<*>)?.message ?: DefaultErrorMessages.render(diagnostic)
diagnostic,
diagnostic.psiFile,
(diagnostic as? MyDiagnostic<*>)?.message ?: DefaultErrorMessages.render(diagnostic)
)
return diagnostic.severity == Severity.ERROR
@@ -159,9 +166,9 @@ class AnalyzerWithCompilerReport(
if (hasIncompatibleClassErrors) {
messageCollector.report(
ERROR,
"Incompatible classes were found in dependencies. " +
"Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors"
ERROR,
"Incompatible classes were found in dependencies. " +
"Remove them from the classpath or use '-Xskip-metadata-version-check' to suppress errors"
)
}
@@ -192,8 +199,10 @@ class AnalyzerWithCompilerReport(
override fun visitErrorElement(element: PsiErrorElement) {
val description = element.errorDescription
reportDiagnostic(element, SYNTAX_ERROR_FACTORY,
if (StringUtil.isEmpty(description)) "Syntax error" else description)
reportDiagnostic(
element, SYNTAX_ERROR_FACTORY,
if (StringUtil.isEmpty(description)) "Syntax error" else description
)
}
}
@@ -210,29 +219,29 @@ class AnalyzerWithCompilerReport(
fun reportBytecodeVersionErrors(bindingContext: BindingContext, messageCollector: MessageCollector) {
val severity =
if (System.getProperty("kotlin.jvm.disable.bytecode.version.error") == "true") STRONG_WARNING
else ERROR
if (System.getProperty("kotlin.jvm.disable.bytecode.version.error") == "true") STRONG_WARNING
else ERROR
val locations = bindingContext.getKeys(IncompatibleClassTrackerImpl.BYTECODE_VERSION_ERRORS)
if (locations.isEmpty()) return
for (location in locations) {
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)
}
}
private fun reportIncompatibleBinaryVersion(
messageCollector: MessageCollector,
data: IncompatibleVersionErrorData<JvmBytecodeBinaryVersion>,
severity: CompilerMessageSeverity
messageCollector: MessageCollector,
data: IncompatibleVersionErrorData<JvmBytecodeBinaryVersion>,
severity: CompilerMessageSeverity
) {
messageCollector.report(
severity,
"Class '" + JvmClassName.byClassId(data.classId) + "' was compiled with an incompatible version of Kotlin. " +
"The binary version of its bytecode is " + data.actualVersion + ", expected version is " + data.expectedVersion,
CompilerMessageLocation.create(toSystemDependentName(data.filePath))
severity,
"Class '" + JvmClassName.byClassId(data.classId) + "' was compiled with an incompatible version of Kotlin. " +
"The binary version of its bytecode is " + data.actualVersion + ", expected version is " + data.expectedVersion,
CompilerMessageLocation.create(toSystemDependentName(data.filePath))
)
}
}
@@ -26,12 +26,11 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
)
}
}
@@ -29,15 +29,13 @@ import org.jetbrains.kotlin.util.ModuleVisibilityHelper
import java.io.File
class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
override fun isInFriendModule(what: DeclarationDescriptor, from: DeclarationDescriptor): Boolean {
val fromSource = getSourceElement(from)
// 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.
val project: Project = if (fromSource is KotlinSourceElement) {
fromSource.psi.project
}
else {
} else {
(from as? LazyPackageDescriptor)?.declarationProvider?.getPackageFiles()?.firstOrNull()?.project ?: return true
}
@@ -70,11 +68,10 @@ class ModuleVisibilityHelperImpl : ModuleVisibilityHelper {
val sourceElement = getSourceElement(descriptor)
return if (sourceElement is KotlinSourceElement) {
modules.singleOrNull() ?: modules.firstOrNull { sourceElement.psi.containingKtFile.virtualFile.path in it.getSourceFiles() }
}
else {
} else {
modules.firstOrNull { module ->
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 {
override val chunk: MutableList<Module> = arrayListOf()
override val friendPaths: MutableList <String> = arrayListOf()
override val friendPaths: MutableList<String> = arrayListOf()
override fun addModule(module: Module) {
chunk.add(module)
@@ -47,4 +47,4 @@ class GarbageCollectionMeasurement(private val garbageCollectionKind: String, pr
class PerformanceCounterMeasurement(private val counterReport: String) : PerformanceMeasurement {
override fun render(): String = counterReport
}
}
@@ -48,4 +48,4 @@ class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
}
}
}
}
}
@@ -27,10 +27,7 @@ import kotlin.concurrent.read
import kotlin.concurrent.write
import kotlin.script.experimental.dependencies.ScriptDependencies
class CliScriptDependenciesProvider(
private val project: Project
) : ScriptDependenciesProvider {
class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
private val cacheLock = ReentrantReadWriteLock()
private val cache = hashMapOf<String, ScriptDependencies?>()
private val scriptContentLoader = ScriptContentLoader(project)
@@ -59,10 +56,9 @@ class CliScriptDependenciesProvider(
cache.put(path, deps)
}
deps
}
else null
} else null
}
}
}
private val log = Logger.getInstance(ScriptDependenciesProvider::class.java)
private val log = Logger.getInstance(ScriptDependenciesProvider::class.java)
@@ -36,7 +36,7 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
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.ERROR -> CompilerMessageSeverity.ERROR
ScriptReport.Severity.WARNING -> CompilerMessageSeverity.WARNING
@@ -44,4 +44,3 @@ class CliScriptReportSink(private val messageCollector: MessageCollector) : Scri
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.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf
import org.jetbrains.kotlin.psi.KtFile
@@ -30,15 +29,16 @@ fun checkKotlinPackageUsage(environment: KotlinCoreEnvironment, files: Collectio
return true
}
val messageCollector = environment.configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val kotlinPackage = FqName.topLevel(Name.identifier("kotlin"))
files.forEach {
if (it.packageFqName.isSubpackageOf(kotlinPackage)) {
messageCollector.report(CompilerMessageSeverity.ERROR,
"Only the Kotlin standard library is allowed to use the 'kotlin' package",
MessageUtil.psiElementToMessageLocation(it.packageDirective!!))
val kotlinPackage = FqName("kotlin")
for (file in files) {
if (file.packageFqName.isSubpackageOf(kotlinPackage)) {
messageCollector.report(
CompilerMessageSeverity.ERROR,
"Only the Kotlin standard library is allowed to use the 'kotlin' package",
MessageUtil.psiElementToMessageLocation(file.packageDirective!!)
)
return false
}
}
return true
}
@@ -24,7 +24,6 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.HashMap;
import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
@@ -106,7 +105,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
}
@NotNull
protected TranslationResult translate(
private static TranslationResult translate(
@NotNull JsConfig.Reporter reporter,
@NotNull List<KtFile> allKotlinFiles,
@NotNull JsAnalysisResult jsAnalysisResult,
@@ -116,7 +115,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
K2JSTranslator translator = new K2JSTranslator(config);
IncrementalDataProvider incrementalDataProvider = config.getConfiguration().get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER);
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) {
nonCompiledSources.put(VfsUtilCore.virtualToIoFile(ktFile.getVirtualFile()), ktFile);
}
@@ -169,7 +168,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
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;
configuration.put(JSConfigurationKeys.LIBRARIES, configureLibraries(arguments, paths, messageCollector));
@@ -249,4 +249,4 @@ class K2JSDce : CLITool<K2JSDceArguments>() {
CLITool.doMain(K2JSDce(), args)
}
}
}
}
@@ -20,11 +20,9 @@ import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
object BundledCompilerPlugins {
val componentRegistrars: List<ComponentRegistrar>
get() = emptyList()
val commandLineProcessors: List<CommandLineProcessor>
get() = emptyList()
}
}
@@ -32,10 +32,10 @@ object JvmRuntimeVersionsConsistencyChecker {
private val LOG = Logger.getInstance(JvmRuntimeVersionsConsistencyChecker::class.java)
private fun <T> T?.assertNotNull(lazyMessage: () -> String): T =
this ?: lazyMessage().let { message ->
LOG.error(message)
throw AssertionError(message)
}
this ?: lazyMessage().let { message ->
LOG.error(message)
throw AssertionError(message)
}
private const val META_INF = "META-INF"
private const val MANIFEST_MF = "$META_INF/MANIFEST.MF"
@@ -51,7 +51,7 @@ object JvmRuntimeVersionsConsistencyChecker {
private const val KOTLIN_REFLECT_MODULE = "$META_INF/kotlin-reflection.kotlin_module"
private val RUNTIME_IMPLEMENTATION_TITLES = setOf(
"kotlin-runtime", "kotlin-stdlib", "kotlin-reflect", "Kotlin Runtime", "Kotlin Standard Library", "Kotlin Reflect"
"kotlin-runtime", "kotlin-stdlib", "kotlin-reflect", "Kotlin Runtime", "Kotlin Standard Library", "Kotlin Reflect"
)
private val KOTLIN_VERSION_ATTRIBUTE: String
@@ -62,44 +62,43 @@ object JvmRuntimeVersionsConsistencyChecker {
init {
val manifestProperties: Properties = try {
JvmRuntimeVersionsConsistencyChecker::class.java
.getResourceAsStream("/kotlinManifest.properties")
.let { input -> Properties().apply { load(input) } }
}
catch (e: Exception) {
.getResourceAsStream("/kotlinManifest.properties")
.let { input -> Properties().apply { load(input) } }
} catch (e: Exception) {
LOG.error(e)
throw e
}
KOTLIN_VERSION_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_VERSION_ATTRIBUTE)
.assertNotNull { "$MANIFEST_KOTLIN_VERSION_ATTRIBUTE not found in kotlinManifest.properties" }
.assertNotNull { "$MANIFEST_KOTLIN_VERSION_ATTRIBUTE not found in kotlinManifest.properties" }
KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT)
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT not found in kotlinManifest.properties" }
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT not found in kotlinManifest.properties" }
KOTLIN_RUNTIME_COMPONENT_CORE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE)
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE not found in kotlinManifest.properties" }
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE not found in kotlinManifest.properties" }
KOTLIN_RUNTIME_COMPONENT_MAIN = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN)
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN not found in kotlinManifest.properties" }
.assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN not found in kotlinManifest.properties" }
}
private class KotlinLibraryFile(val file: VirtualFile, val version: MavenComparableVersion) {
override fun toString(): String =
"${file.name}:$version"
"${file.name}:$version"
}
private class RuntimeJarsInfo(
// Runtime jars with components "Main" and "Core"
val jars: List<KotlinLibraryFile>,
// Runtime jars with components "Core" only (a subset of [jars])
val coreJars: List<KotlinLibraryFile>,
// Library jars which have some Kotlin Runtime library bundled into them
val otherLibrariesWithBundledRuntime: List<VirtualFile>,
val stdlibJre7: List<KotlinLibraryFile>,
val stdlibJre8: List<KotlinLibraryFile>
// Runtime jars with components "Main" and "Core"
val jars: List<KotlinLibraryFile>,
// Runtime jars with components "Core" only (a subset of [jars])
val coreJars: List<KotlinLibraryFile>,
// Library jars which have some Kotlin Runtime library bundled into them
val otherLibrariesWithBundledRuntime: List<VirtualFile>,
val stdlibJre7: List<KotlinLibraryFile>,
val stdlibJre8: List<KotlinLibraryFile>
)
fun checkCompilerClasspathConsistency(
messageCollector: MessageCollector,
configuration: CompilerConfiguration,
classpathJarRoots: List<VirtualFile>
messageCollector: MessageCollector,
configuration: CompilerConfiguration,
classpathJarRoots: List<VirtualFile>
) {
val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots)
if (runtimeJarsInfo.jars.isEmpty()) return
@@ -114,11 +113,11 @@ object JvmRuntimeVersionsConsistencyChecker {
messageCollector.issue(
null,
"Runtime JAR files in the classpath have the version $actualRuntimeVersion, " +
"which is older than the API version ${currentApi.version}. " +
"Consider using the runtime of version ${currentApi.version}, or pass '-api-version $actualRuntimeVersion' " +
"explicitly to restrict the available APIs to the runtime of version $actualRuntimeVersion. " +
"You can also pass '-language-version $actualRuntimeVersion' instead, which will restrict " +
"not only the APIs to the specified version, but also the language features"
"which is older than the API version ${currentApi.version}. " +
"Consider using the runtime of version ${currentApi.version}, or pass '-api-version $actualRuntimeVersion' " +
"explicitly to restrict the available APIs to the runtime of version $actualRuntimeVersion. " +
"You can also pass '-language-version $actualRuntimeVersion' instead, which will restrict " +
"not only the APIs to the specified version, but also the language features"
)
for (jar in consistency.incompatibleJars) {
@@ -141,17 +140,18 @@ object JvmRuntimeVersionsConsistencyChecker {
override val apiVersion: ApiVersion get() = actualApi
}
messageCollector.issue(null, "Old runtime has been found in the classpath. " +
"Initial language version settings: $languageVersionSettings. " +
"Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING)
messageCollector.issue(
null, "Old runtime has been found in the classpath. " +
"Initial language version settings: $languageVersionSettings. " +
"Updated language version settings: $newSettings", CompilerMessageSeverity.LOGGING
)
configuration.languageVersionSettings = newSettings
}
}
else if (consistency != ClasspathConsistency.Consistent) {
} else if (consistency != ClasspathConsistency.Consistent) {
messageCollector.issue(
null,
"Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath"
null,
"Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath"
)
}
@@ -167,10 +167,10 @@ object JvmRuntimeVersionsConsistencyChecker {
val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime
if (librariesWithBundled.isNotEmpty()) {
messageCollector.issue(
null,
"Some JAR files in the classpath have the Kotlin Runtime library bundled into them. " +
"This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the classpath. " +
"Consider removing these libraries from the classpath"
null,
"Some JAR files in the classpath have the Kotlin Runtime library bundled into them. " +
"This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the classpath. " +
"Consider removing these libraries from the classpath"
)
for (library in librariesWithBundled) {
@@ -185,14 +185,15 @@ object JvmRuntimeVersionsConsistencyChecker {
val actualRuntimeVersion: MavenComparableVersion,
val incompatibleJars: List<KotlinLibraryFile>
) : ClasspathConsistency()
object InconsistentWithCompilerVersion : ClasspathConsistency()
object InconsistentBecauseOfRuntimesWithDifferentVersions : ClasspathConsistency()
}
private fun checkCompilerClasspathConsistency(
messageCollector: MessageCollector,
apiVersion: MavenComparableVersion,
runtimeJarsInfo: RuntimeJarsInfo
messageCollector: MessageCollector,
apiVersion: MavenComparableVersion,
runtimeJarsInfo: RuntimeJarsInfo
): ClasspathConsistency {
// The "Core" jar files should not be newer than the compiler. This behavior is reserved for the future if we realise that we're
// going to break language/library compatibility in such a way that it's easier to make the old compiler just report an error
@@ -206,7 +207,7 @@ object JvmRuntimeVersionsConsistencyChecker {
if (jars.isEmpty()) return ClasspathConsistency.Consistent
val runtimeVersion = checkMatchingVersionsAndGetRuntimeVersion(messageCollector, jars)
?: return ClasspathConsistency.InconsistentBecauseOfRuntimesWithDifferentVersions
?: return ClasspathConsistency.InconsistentBecauseOfRuntimesWithDifferentVersions
val jarsIncompatibleWithApiVersion = jars.filter { it.version < apiVersion }
if (jarsIncompatibleWithApiVersion.isNotEmpty()) {
@@ -219,9 +220,9 @@ object JvmRuntimeVersionsConsistencyChecker {
private fun checkNotNewerThanCompiler(messageCollector: MessageCollector, jar: KotlinLibraryFile): Boolean {
if (jar.version > ApiVersion.LATEST_STABLE.version) {
messageCollector.issue(
jar.file,
"Runtime JAR file has version ${jar.version} which is newer than compiler version ${ApiVersion.LATEST_STABLE.version}",
CompilerMessageSeverity.ERROR
jar.file,
"Runtime JAR file has version ${jar.version} which is newer than compiler version ${ApiVersion.LATEST_STABLE.version}",
CompilerMessageSeverity.ERROR
)
return true
}
@@ -230,8 +231,8 @@ object JvmRuntimeVersionsConsistencyChecker {
// Returns the version if it's the same across all jars, or null if versions of some jars differ.
private fun checkMatchingVersionsAndGetRuntimeVersion(
messageCollector: MessageCollector,
jars: List<KotlinLibraryFile>
messageCollector: MessageCollector,
jars: List<KotlinLibraryFile>
): MavenComparableVersion? {
assert(jars.isNotEmpty()) { "'jars' must not be empty" }
val oldestVersion = jars.minBy { it.version }!!.version
@@ -251,13 +252,13 @@ object JvmRuntimeVersionsConsistencyChecker {
// we suggest to provide an explicit dependency on version X.
// TODO: report this depending on the content of the jars instead
val minReflectJar =
jars.filter { it.file.name.startsWith("kotlin-reflect") }.minBy { it.version }
jars.filter { it.file.name.startsWith("kotlin-reflect") }.minBy { it.version }
val maxStdlibJar =
jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxBy { it.version }
jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxBy { it.version }
if (minReflectJar != null && maxStdlibJar != null && minReflectJar.version < maxStdlibJar.version) {
messageCollector.issue(
null,
"Consider providing an explicit dependency on kotlin-reflect ${maxStdlibJar.version} to prevent strange errors"
null,
"Consider providing an explicit dependency on kotlin-reflect ${maxStdlibJar.version} to prevent strange errors"
)
}
@@ -265,9 +266,9 @@ object JvmRuntimeVersionsConsistencyChecker {
}
private fun MessageCollector.issue(
file: VirtualFile?,
message: String,
severity: CompilerMessageSeverity = CompilerMessageSeverity.STRONG_WARNING
file: VirtualFile?,
message: String,
severity: CompilerMessageSeverity = CompilerMessageSeverity.STRONG_WARNING
) {
report(severity, message, CompilerMessageLocation.create(file?.let(VfsUtilCore::virtualToIoFile)?.path))
}
@@ -330,8 +331,7 @@ object JvmRuntimeVersionsConsistencyChecker {
val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF)
val manifest = try {
manifestFile?.let { Manifest(it.inputStream) }
}
catch (e: IOException) {
} catch (e: IOException) {
return FileKind.Irrelevant
}
@@ -345,7 +345,7 @@ object JvmRuntimeVersionsConsistencyChecker {
FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = true)
null -> when {
jarRoot.findFileByRelativePath(KOTLIN_STDLIB_MODULE) == null &&
jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant
jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant
isGenuineKotlinRuntime(manifest) -> FileKind.OldRuntime
else -> FileKind.LibraryWithBundledRuntime
}
@@ -356,9 +356,9 @@ object JvmRuntimeVersionsConsistencyChecker {
// Returns true if the manifest is from the original Kotlin Runtime jar, false if it's from a library with a bundled runtime
private fun isGenuineKotlinRuntime(manifest: Manifest?): Boolean {
return manifest != null &&
manifest.mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE) in RUNTIME_IMPLEMENTATION_TITLES
manifest.mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE) in RUNTIME_IMPLEMENTATION_TITLES
}
private fun Manifest.getKotlinLanguageVersion(): MavenComparableVersion =
(mainAttributes.getValue(KOTLIN_VERSION_ATTRIBUTE)?.let((ApiVersion)::parse) ?: ApiVersion.KOTLIN_1_0).version
(mainAttributes.getValue(KOTLIN_VERSION_ATTRIBUTE)?.let((ApiVersion)::parse) ?: ApiVersion.KOTLIN_1_0).version
}
@@ -150,7 +150,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
KotlinToJVMBytecodeCompiler.configureSourceRoots(configuration, moduleChunk.modules, buildFile)
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
?: return COMPILATION_ERROR
?: return COMPILATION_ERROR
registerJavacIfNeeded(environment, arguments).let {
if (!it) return COMPILATION_ERROR
@@ -164,7 +164,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
?: return COMPILATION_ERROR
?: return COMPILATION_ERROR
val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(environment.project)
val scriptFile = File(sourcePath)
@@ -188,7 +188,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
}
val environment = createCoreEnvironment(rootDisposable, configuration, messageCollector)
?: return COMPILATION_ERROR
?: return COMPILATION_ERROR
registerJavacIfNeeded(environment, arguments).let {
if (!it) return COMPILATION_ERROR
@@ -208,7 +208,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
if (!it) return COMPILATION_ERROR
}
}
return OK
} catch (e: CompilationException) {
messageCollector.report(
@@ -243,7 +243,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
val jars = arrayOf(
KOTLIN_SCRIPTING_COMPILER_PLUGIN_JAR, KOTLIN_SCRIPTING_COMMON_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) {
pluginClasspaths = jars + pluginClasspaths
}
@@ -308,19 +308,19 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration: CompilerConfiguration, arguments: K2JVMCompilerArguments, services: Services
) {
if (IncrementalCompilation.isEnabledForJvm()) {
services.get(LookupTracker::class.java)?.let {
services[LookupTracker::class.java]?.let {
configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, it)
}
services.get(ExpectActualTracker::class.java)?.let {
services[ExpectActualTracker::class.java]?.let {
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)
}
services.get(JavaClassesTracker::class.java)?.let {
services[JavaClassesTracker::class.java]?.let {
configuration.put(JVMConfigurationKeys.JAVA_CLASSES_TRACKER, it)
}
}
@@ -46,13 +46,13 @@ import java.util.jar.Manifest
import kotlin.LazyThreadSafetyMode.NONE
class ClasspathRootsResolver(
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
) {
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
@@ -80,9 +80,9 @@ class ClasspathRootsResolver(
}
private fun computeRoots(
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
): RootsAndModules {
val result = mutableListOf<JavaRoot>()
val modules = mutableListOf<JavaModule>()
@@ -93,8 +93,7 @@ class ClasspathRootsResolver(
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) {
modules += modularRoot
}
else {
} else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also {
@@ -128,11 +127,11 @@ class ClasspathRootsResolver(
private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? {
val moduleInfoFile =
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
val psiFile = psiManager.findFile(moduleInfoFile) ?: return null
val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null
@@ -144,9 +143,9 @@ class ClasspathRootsResolver(
val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null
val sourceRoot = JavaModule.Root(root, isBinary = false)
val roots =
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile)
}
@@ -155,7 +154,7 @@ class ClasspathRootsResolver(
val manifest: Attributes? by lazy(NONE) { readManifestAttributes(root) }
val moduleInfoFile =
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
?: root.takeIf { isJar }?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE)?.takeIf {
manifest?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true) == true
}
@@ -190,8 +189,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
}
catch (e: IOException) {
} catch (e: IOException) {
null
}
}
@@ -211,16 +209,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name)
if (existing == null) {
javaModuleFinder.addUserModule(module)
}
else if (module.moduleRoots != existing.moduleRoots) {
} else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile()
val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}"
report(STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile)
report(
STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile
)
}
}
@@ -257,8 +256,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName)
if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph")
}
else {
} else {
for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
}
@@ -267,10 +265,10 @@ class ClasspathRootsResolver(
if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
report(
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
)
}
}
@@ -314,8 +312,8 @@ class ClasspathRootsResolver(
throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)")
}
messageCollector.report(
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
)
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -47,13 +46,13 @@ import java.util.jar.Manifest
import kotlin.LazyThreadSafetyMode.NONE
class ClasspathRootsResolver(
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
) {
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
@@ -81,9 +80,9 @@ class ClasspathRootsResolver(
}
private fun computeRoots(
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
): RootsAndModules {
val result = mutableListOf<JavaRoot>()
val modules = mutableListOf<JavaModule>()
@@ -92,22 +91,21 @@ class ClasspathRootsResolver(
for ((root, packagePrefix) in javaSourceRoots) {
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) {
modules += modularRoot
}
else {
if (modularRoot != null) {
modules += modularRoot
} else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also {
report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix")
}
})
if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also {
report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix")
}
}
})
}
}
for (root in jvmClasspathRoots) {
result += JavaRoot(root, JavaRoot.RootType.BINARY)
}
result += JavaRoot(root, JavaRoot.RootType.BINARY)
}
val outputDirectoryAddedAsPartOfModule = modules.any { module -> module.moduleRoots.any { it.file == outputDirectory } }
@@ -117,24 +115,24 @@ class ClasspathRootsResolver(
if (outputDirectoryAddedAsPartOfModule && root == outputDirectory) continue
val module = modularBinaryRoot(root)
if (module != null) {
modules += module
}
}
if (module != null) {
modules += module
}
}
addModularRoots(modules, result)
return RootsAndModules(result, modules)
}
/*
/*
private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? {
val moduleInfoFile =
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
val psiFile = psiManager.findFile(moduleInfoFile) ?: return null
val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null
@@ -148,9 +146,9 @@ class ClasspathRootsResolver(
val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null
val sourceRoot = JavaModule.Root(root, isBinary = false)
val roots =
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile)
*/
return null
@@ -162,7 +160,7 @@ class ClasspathRootsResolver(
/*
val moduleInfoFile =
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
?: root.takeIf { isJar }?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE)?.takeIf {
manifest?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true) == true
}
@@ -198,8 +196,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
}
catch (e: IOException) {
} catch (e: IOException) {
null
}
}
@@ -219,16 +216,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name)
if (existing == null) {
javaModuleFinder.addUserModule(module)
}
else if (module.moduleRoots != existing.moduleRoots) {
} else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile()
val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}"
report(STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile)
report(
STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile
)
}
}
@@ -265,8 +263,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName)
if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph")
}
else {
} else {
for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
}
@@ -275,10 +272,10 @@ class ClasspathRootsResolver(
if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
report(
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
)
}
}
@@ -322,8 +319,8 @@ class ClasspathRootsResolver(
throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)")
}
messageCollector.report(
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
)
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -47,13 +46,13 @@ import java.util.jar.Manifest
import kotlin.LazyThreadSafetyMode.NONE
class ClasspathRootsResolver(
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
private val psiManager: PsiManager,
private val messageCollector: MessageCollector?,
private val additionalModules: List<String>,
private val contentRootToVirtualFile: (JvmContentRoot) -> VirtualFile?,
private val javaModuleFinder: CliJavaModuleFinder,
private val requireStdlibModule: Boolean,
private val outputDirectory: VirtualFile?
) {
val javaModuleGraph = JavaModuleGraph(javaModuleFinder)
@@ -81,9 +80,9 @@ class ClasspathRootsResolver(
}
private fun computeRoots(
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
javaSourceRoots: List<RootWithPrefix>,
jvmClasspathRoots: List<VirtualFile>,
jvmModulePathRoots: List<VirtualFile>
): RootsAndModules {
val result = mutableListOf<JavaRoot>()
val modules = mutableListOf<JavaModule>()
@@ -92,22 +91,21 @@ class ClasspathRootsResolver(
for ((root, packagePrefix) in javaSourceRoots) {
val modularRoot = modularSourceRoot(root, hasOutputDirectoryInClasspath)
if (modularRoot != null) {
modules += modularRoot
}
else {
if (modularRoot != null) {
modules += modularRoot
} else {
result += JavaRoot(root, JavaRoot.RootType.SOURCE, packagePrefix?.let { prefix ->
if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also {
report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix")
}
})
if (isValidJavaFqName(prefix)) FqName(prefix)
else null.also {
report(STRONG_WARNING, "Invalid package prefix name is ignored: $prefix")
}
}
})
}
}
for (root in jvmClasspathRoots) {
result += JavaRoot(root, JavaRoot.RootType.BINARY)
}
result += JavaRoot(root, JavaRoot.RootType.BINARY)
}
val outputDirectoryAddedAsPartOfModule = modules.any { module -> module.moduleRoots.any { it.file == outputDirectory } }
@@ -117,24 +115,24 @@ class ClasspathRootsResolver(
if (outputDirectoryAddedAsPartOfModule && root == outputDirectory) continue
val module = modularBinaryRoot(root)
if (module != null) {
modules += module
}
}
if (module != null) {
modules += module
}
}
addModularRoots(modules, result)
return RootsAndModules(result, modules)
}
/*
/*
private fun findSourceModuleInfo(root: VirtualFile): Pair<VirtualFile, PsiJavaModule>? {
val moduleInfoFile =
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
when {
root.isDirectory -> root.findChild(PsiJavaModule.MODULE_INFO_FILE)
root.name == PsiJavaModule.MODULE_INFO_FILE -> root
else -> null
} ?: return null
val psiFile = psiManager.findFile(moduleInfoFile) ?: return null
val psiJavaModule = psiFile.children.singleOrNull { it is PsiJavaModule } as? PsiJavaModule ?: return null
@@ -148,9 +146,9 @@ class ClasspathRootsResolver(
val (moduleInfoFile, psiJavaModule) = findSourceModuleInfo(root) ?: return null
val sourceRoot = JavaModule.Root(root, isBinary = false)
val roots =
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
if (hasOutputDirectoryInClasspath)
listOf(sourceRoot, JavaModule.Root(outputDirectory!!, isBinary = true))
else listOf(sourceRoot)
return JavaModule.Explicit(JavaModuleInfo.create(psiJavaModule), roots, moduleInfoFile)
*/
return null
@@ -162,7 +160,7 @@ class ClasspathRootsResolver(
/*
val moduleInfoFile =
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
root.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)
?: root.takeIf { isJar }?.findFileByRelativePath(MULTI_RELEASE_MODULE_INFO_CLS_FILE)?.takeIf {
manifest?.getValue(IS_MULTI_RELEASE)?.equals("true", ignoreCase = true) == true
}
@@ -198,8 +196,7 @@ class ClasspathRootsResolver(
val manifestFile = jarRoot.findChild("META-INF")?.findChild("MANIFEST.MF")
return try {
manifestFile?.inputStream?.let(::Manifest)?.mainAttributes
}
catch (e: IOException) {
} catch (e: IOException) {
null
}
}
@@ -219,16 +216,17 @@ class ClasspathRootsResolver(
val existing = javaModuleFinder.findModule(module.name)
if (existing == null) {
javaModuleFinder.addUserModule(module)
}
else if (module.moduleRoots != existing.moduleRoots) {
} else if (module.moduleRoots != existing.moduleRoots) {
fun JavaModule.getRootFile() =
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
moduleRoots.firstOrNull()?.file?.let { VfsUtilCore.getVirtualFileForJar(it) ?: it }
val thisFile = module.getRootFile()
val existingFile = existing.getRootFile()
val atExistingPath = if (existingFile == null) "" else " at: ${existingFile.path}"
report(STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile)
report(
STRONG_WARNING, "The root is ignored because a module with the same name '${module.name}' " +
"has been found earlier on the module path$atExistingPath", thisFile
)
}
}
@@ -265,8 +263,7 @@ class ClasspathRootsResolver(
val module = javaModuleFinder.findModule(moduleName)
if (module == null) {
report(ERROR, "Module $moduleName cannot be found in the module graph")
}
else {
} else {
for ((root, isBinary) in module.moduleRoots) {
result.add(JavaRoot(root, if (isBinary) JavaRoot.RootType.BINARY else JavaRoot.RootType.SOURCE))
}
@@ -275,10 +272,10 @@ class ClasspathRootsResolver(
if (requireStdlibModule && sourceModule != null && !javaModuleGraph.reads(sourceModule.name, KOTLIN_STDLIB_MODULE_NAME)) {
report(
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
ERROR,
"The Kotlin standard library is not found in the module graph. " +
"Please ensure you have the 'requires $KOTLIN_STDLIB_MODULE_NAME' clause in your module definition",
sourceModule.moduleInfoFile
)
}
}
@@ -322,8 +319,8 @@ class ClasspathRootsResolver(
throw IllegalStateException("${if (file != null) file.path + ":" else ""}$severity: $message (no MessageCollector configured)")
}
messageCollector.report(
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
severity, message,
if (file == null) null else CompilerMessageLocation.create(MessageUtil.virtualFileToPath(file))
)
}
@@ -10,15 +10,12 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchScopeUtil
import com.intellij.util.Function
import com.intellij.util.SmartList
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer
@@ -35,19 +32,14 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
class CliKotlinAsJavaSupport(
project: Project,
private val traceHolder: CliTraceHolder
): KotlinAsJavaSupport() {
) : KotlinAsJavaSupport() {
private val psiManager = PsiManager.getInstance(project)
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
return findFacadeFilesInPackage(packageFqName, scope)
.groupBy { it.javaFileFacadeFqName }
.mapNotNull {
KtLightClassForFacade.createForFacade(
psiManager,
it.key,
scope,
it.value
)
.mapNotNull { (facadeClassFqName, files) ->
KtLightClassForFacade.createForFacade(psiManager, facadeClassFqName, scope, files)
}
}
@@ -67,13 +59,8 @@ class CliKotlinAsJavaSupport(
val filesForFacade = findFilesForFacade(facadeFqName, scope)
if (filesForFacade.isEmpty()) return emptyList()
return listOfNotNull<PsiClass>(
KtLightClassForFacade.createForFacade(
psiManager,
facadeFqName,
scope,
filesForFacade
)
return listOfNotNull(
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade)
)
}
@@ -88,7 +75,6 @@ class CliKotlinAsJavaSupport(
}
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
//
return emptyList()
}
@@ -97,7 +83,7 @@ class CliKotlinAsJavaSupport(
return traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_FQ_NAME, facadeFqName)?.filter {
PsiSearchScopeUtil.isInScope(scope, it)
} ?: emptyList()
}.orEmpty()
}
@@ -122,20 +108,10 @@ class CliKotlinAsJavaSupport(
override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName> {
val packageView = traceHolder.module.getPackage(fqn)
val members = packageView.memberScope.getContributedDescriptors(
return packageView.memberScope.getContributedDescriptors(
DescriptorKindFilter.PACKAGES,
MemberScope.ALL_NAME_FILTER
)
return ContainerUtil.mapNotNull(
members,
object : Function<DeclarationDescriptor, FqName> {
override fun `fun`(member: DeclarationDescriptor): FqName? {
if (member is PackageViewDescriptor) {
return member.fqName
}
return null
}
})
).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName }
}
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? =
@@ -144,24 +120,18 @@ class CliKotlinAsJavaSupport(
override fun getLightClassForScript(script: KtScript): KtLightClassForScript? =
KtLightClassForScript.create(script)
override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> {
return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull {
val element = DescriptorToSourceUtils.getSourceFromDescriptor(it)
if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope(
searchScope,
element
)
) {
if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) {
element
}
else null
} else null
}
}
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> {
return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter {
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
*/
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
override fun createDataHolderForClass(
classOrObject: KtClassOrObject, builder: LightClassBuilder
): LightClassDataHolder.ForClass {
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
//force resolve companion for light class generation
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
@@ -49,10 +47,7 @@ class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) :
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassDataHolder
return LightClassDataHolderImpl(
stub,
diagnostics
)
return LightClassDataHolderImpl(stub, diagnostics)
}
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
}
@@ -45,7 +45,7 @@ class CliTraceHolder : CodeAnalyzerInitializer {
// TODO: needs better name + list of keys to skip somewhere
class NoScopeRecordCliBindingTrace : CliBindingTrace() {
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
return
}
@@ -29,16 +29,19 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial
import java.io.InputStream
class CliVirtualFileFinder(
private val index: JvmDependenciesIndex,
private val scope: GlobalSearchScope
private val index: JvmDependenciesIndex,
private val scope: GlobalSearchScope
) : VirtualFileFinder() {
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? =
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
findBinaryClass(classId, classId.relativeClassName.asString().replace('.', '$') + ".class")
override fun findMetadata(classId: ClassId): InputStream? {
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 {
@@ -59,7 +62,7 @@ class CliVirtualFileFinder(
}
private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? =
index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
dir.findChild(fileName)?.takeIf(VirtualFile::isValid)
}?.takeIf { it in scope }
index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
dir.findChild(fileName)?.takeIf(VirtualFile::isValid)
}?.takeIf { it in scope }
}
@@ -21,10 +21,6 @@ public class CompileEnvironmentException extends RuntimeException {
super(message);
}
public CompileEnvironmentException(Throwable cause) {
super(cause);
}
public CompileEnvironmentException(String message, Throwable cause) {
super(message, cause);
}
@@ -73,7 +73,9 @@ public class CompileEnvironmentUtil {
}
// 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 {
Manifest manifest = new Manifest();
Attributes mainAttributes = manifest.getMainAttributes();
@@ -31,8 +31,8 @@ import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
import java.io.EOFException
class JvmPackagePartProvider(
languageVersionSettings: LanguageVersionSettings,
private val scope: GlobalSearchScope
languageVersionSettings: LanguageVersionSettings,
private val scope: GlobalSearchScope
) : PackagePartProvider, MetadataPartProvider {
private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping, val name: String)
@@ -59,7 +59,7 @@ class JvmPackagePartProvider(
}
override fun findMetadataPackageParts(packageFqName: String): List<String> =
getPackageParts(packageFqName).values.flatMap(PackageParts::metadataParts).distinct()
getPackageParts(packageFqName).values.flatMap(PackageParts::metadataParts).distinct()
@Synchronized
private fun getPackageParts(packageFqName: String): Map<VirtualFile, PackageParts> {
@@ -53,10 +53,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private var useFastClassFilesReading = false
fun initialize(
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
) {
this.index = index
this.packagePartProviders = packagePartProviders
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type)
}
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
} ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope }
}
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent =
BinaryClassSignatureParser()
private val signatureParsingComponent = BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(
virtualFile,
classId.asSingleFqName(),
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
outerClass = null, classContent = classContent
)
}
}
@@ -142,9 +136,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
if (packageFqName.isRoot) break
classId = ClassId(
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
)
}
}
@@ -155,9 +149,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val relativeClassName = classId.relativeClassName.asString()
index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
val psiClass =
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
if (psiClass != null) {
result.add(psiClass)
}
@@ -166,9 +160,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
if (result.isNotEmpty()) {
@@ -197,9 +191,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
private fun findVirtualFileGivenPackage(
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
): VirtualFile? {
val topLevelClassName = classNameWithInnerClasses.substringBefore('.')
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile
}
private fun VirtualFile.findPsiClassInVirtualFile(
classNameWithInnerClasses: String
): PsiClass? {
private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file)
}
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = {
dir, _ ->
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") {
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
private fun <T : Any> safely(compute: () -> T): T? = try {
compute()
}
catch (e: IllegalArgumentException) {
null
}
catch (e: AssertionError) {
null
}
private fun <T : Any> safely(compute: () -> T): T? =
try {
compute()
} catch (e: IllegalArgumentException) {
null
} catch (e: AssertionError) {
null
}
private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -53,10 +53,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private var useFastClassFilesReading = false
fun initialize(
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
) {
this.index = index
this.packagePartProviders = packagePartProviders
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type)
}
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
} ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope }
}
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent =
BinaryClassSignatureParser()
private val signatureParsingComponent = BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(
virtualFile,
classId.asSingleFqName(),
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
outerClass = null, classContent = classContent
)
}
}
@@ -142,9 +136,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
if (packageFqName.isRoot) break
classId = ClassId(
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
)
}
}
@@ -155,9 +149,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val relativeClassName = classId.relativeClassName.asString()
index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
val psiClass =
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
if (psiClass != null) {
result.add(psiClass)
}
@@ -166,9 +160,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
if (result.isNotEmpty()) {
@@ -197,9 +191,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
private fun findVirtualFileGivenPackage(
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
): VirtualFile? {
val topLevelClassName = classNameWithInnerClasses.substringBefore('.')
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile
}
private fun VirtualFile.findPsiClassInVirtualFile(
classNameWithInnerClasses: String
): PsiClass? {
private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file)
}
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = {
dir, _ ->
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") {
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
private fun <T : Any> safely(compute: () -> T): T? = try {
compute()
}
catch (e: IllegalArgumentException) {
null
}
catch (e: AssertionError) {
null
}
private fun <T : Any> safely(compute: () -> T): T? =
try {
compute()
} catch (e: IllegalArgumentException) {
null
} catch (e: AssertionError) {
null
}
private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -53,10 +53,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private var useFastClassFilesReading = false
fun initialize(
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
index: JvmDependenciesIndex,
packagePartProviders: List<JvmPackagePartProvider>,
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
useFastClassFilesReading: Boolean
) {
this.index = index
this.packagePartProviders = packagePartProviders
@@ -73,14 +73,12 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) {
index.findClass(classId) { dir, type ->
findVirtualFileGivenPackage(dir, relativeClassName, type)
}
?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
} ?: singleJavaFileRootsIndex.findJavaSourceClass(classId)
}?.takeIf { it in searchScope }
}
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent =
BinaryClassSignatureParser()
private val signatureParsingComponent = BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
@@ -103,12 +101,8 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(
virtualFile,
classId.asSingleFqName(),
resolver,
signatureParsingComponent,
outerClass = null,
classContent = classContent
virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent,
outerClass = null, classContent = classContent
)
}
}
@@ -142,9 +136,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
if (packageFqName.isRoot) break
classId = ClassId(
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
packageFqName.parent(),
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
false
)
}
}
@@ -155,9 +149,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val relativeClassName = classId.relativeClassName.asString()
index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
val psiClass =
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
if (psiClass != null) {
result.add(psiClass)
}
@@ -166,9 +160,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
if (result.isNotEmpty()) {
@@ -197,9 +191,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
}
private fun findVirtualFileGivenPackage(
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
packageDir: VirtualFile,
classNameWithInnerClasses: String,
rootType: JavaRoot.RootType
): VirtualFile? {
val topLevelClassName = classNameWithInnerClasses.substringBefore('.')
@@ -216,18 +210,14 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
return vFile
}
private fun VirtualFile.findPsiClassInVirtualFile(
classNameWithInnerClasses: String
): PsiClass? {
private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? {
val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null
return findClassInPsiFile(classNameWithInnerClasses, file)
}
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> {
val result = hashSetOf<String>()
index.traverseDirectoriesInPackage(packageFqName, continueSearch = {
dir, _ ->
index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ ->
for (child in dir.children) {
if (child.extension == "class" || child.extension == "java") {
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
private fun <T : Any> safely(compute: () -> T): T? = try {
compute()
}
catch (e: IllegalArgumentException) {
null
}
catch (e: AssertionError) {
null
}
private fun <T : Any> safely(compute: () -> T): T? =
try {
compute()
} catch (e: IllegalArgumentException) {
null
} catch (e: AssertionError) {
null
}
private fun String.toSafeFqName(): FqName? = safely { FqName(this) }
private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) }
@@ -246,7 +246,7 @@ class KotlinCoreEnvironment private constructor(
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)?.absolutePath
?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)?.absolutePath
classpathRootsResolver = ClasspathRootsResolver(
PsiManager.getInstance(project),
@@ -554,14 +554,14 @@ class KotlinCoreEnvironment private constructor(
val pluginRoot =
configuration.get(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT)?.let(::File)
?: configuration.get(CLIConfigurationKeys.COMPILER_JAR_LOCATOR)?.compilerJar
?: PathUtil.getResourcePathForClass(this::class.java).takeIf { it.hasConfigFile(configFilePath) }
// hack for load extensions when compiler run directly from project directory (e.g. in tests)
?: File("idea/src").takeIf { it.hasConfigFile(configFilePath) }
?: throw IllegalStateException(
"Unable to find extension point configuration $configFilePath " +
"(cp:\n ${(Thread.currentThread().contextClassLoader as? UrlClassLoader)?.urls?.joinToString("\n ") { it.file }})"
)
?: configuration.get(CLIConfigurationKeys.COMPILER_JAR_LOCATOR)?.compilerJar
?: PathUtil.getResourcePathForClass(this::class.java).takeIf { it.hasConfigFile(configFilePath) }
// hack for load extensions when compiler run directly from project directory (e.g. in tests)
?: File("idea/src").takeIf { it.hasConfigFile(configFilePath) }
?: throw IllegalStateException(
"Unable to find extension point configuration $configFilePath " +
"(cp:\n ${(Thread.currentThread().contextClassLoader as? UrlClassLoader)?.urls?.joinToString("\n ") { it.file }})"
)
CoreApplicationEnvironment.registerExtensionPointAndExtensions(pluginRoot, configFilePath, Extensions.getRootArea())
}
@@ -20,11 +20,10 @@ import com.intellij.core.JavaCoreApplicationEnvironment
import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.openapi.Disposable
import com.intellij.psi.PsiManager
import com.intellij.psi.controlFlow.ControlFlowFactory
open class KotlinCoreProjectEnvironment(
disposable: Disposable,
applicationEnvironment: JavaCoreApplicationEnvironment
disposable: Disposable,
applicationEnvironment: JavaCoreApplicationEnvironment
) : JavaCoreProjectEnvironment(disposable, applicationEnvironment) {
override fun createCoreFileManager() = KotlinCliJavaFileManagerImpl(PsiManager.getInstance(project))
}
}
@@ -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.SimpleOutputFileCollection
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.CompilerMessageSeverity.OUTPUT
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.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler {
@@ -159,12 +159,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory()))
}
} else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let {
it.report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files"
)
}
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " +
"-Xuse-javac option couldn't be used to compile java files"
)
JavacWrapper.getInstance(environment.project).close()
}
}
@@ -257,7 +256,7 @@ object KotlinToJVMBytecodeCompiler {
try {
try {
tryConstructClassFromStringArgs(scriptClass, scriptArgs)
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
} finally {
// NB: these lines are required (see KT-9546) but aren't covered by tests
System.out.flush()
@@ -335,11 +334,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e)
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
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.OutputMessageUtil
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.codegen.*
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.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler {
@@ -161,12 +158,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory()))
}
} else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let {
it.report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files"
)
}
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " +
"-Xuse-javac option couldn't be used to compile java files"
)
JavacWrapper.getInstance(environment.project).close()
}
}
@@ -192,8 +188,8 @@ object KotlinToJVMBytecodeCompiler {
module.getJavaSourceRoots().any { (path, packagePrefix) ->
val file = File(path)
packagePrefix == null &&
(file.name == PsiJavaModule.MODULE_INFO_FILE ||
(file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE }))
(file.name == PsiJavaModule.MODULE_INFO_FILE ||
(file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE }))
}
}*/
@@ -259,7 +255,7 @@ object KotlinToJVMBytecodeCompiler {
try {
try {
tryConstructClassFromStringArgs(scriptClass, scriptArgs)
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
} finally {
// NB: these lines are required (see KT-9546) but aren't covered by tests
System.out.flush()
@@ -337,11 +333,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e)
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
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.OutputMessageUtil
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.codegen.*
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.psi.KtFile
import org.jetbrains.kotlin.script.tryConstructClassFromStringArgs
import org.jetbrains.kotlin.util.PerformanceCounter
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
import java.io.File
import java.lang.reflect.InvocationTargetException
import java.net.URLClassLoader
import java.util.concurrent.TimeUnit
object KotlinToJVMBytecodeCompiler {
@@ -161,12 +158,11 @@ object KotlinToJVMBytecodeCompiler {
it.compile(File(singleModule.getOutputDirectory()))
}
} else {
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let {
it.report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files"
)
}
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
WARNING,
"A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). " +
"-Xuse-javac option couldn't be used to compile java files"
)
JavacWrapper.getInstance(environment.project).close()
}
}
@@ -192,8 +188,8 @@ object KotlinToJVMBytecodeCompiler {
module.getJavaSourceRoots().any { (path, packagePrefix) ->
val file = File(path)
packagePrefix == null &&
(file.name == PsiJavaModule.MODULE_INFO_FILE ||
(file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE }))
(file.name == PsiJavaModule.MODULE_INFO_FILE ||
(file.isDirectory && file.listFiles().any { it.name == PsiJavaModule.MODULE_INFO_FILE }))
}
}*/
@@ -259,7 +255,7 @@ object KotlinToJVMBytecodeCompiler {
try {
try {
tryConstructClassFromStringArgs(scriptClass, scriptArgs)
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs\n")
} finally {
// NB: these lines are required (see KT-9546) but aren't covered by tests
System.out.flush()
@@ -337,11 +333,11 @@ object KotlinToJVMBytecodeCompiler {
val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed")
return classLoader.loadClass(script.fqName.asString())
} catch (e: Exception) {
throw RuntimeException("Failed to evaluate script: " + e, e)
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
if (!result.shouldGenerateCode) return null
@@ -30,7 +30,12 @@ class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
override fun findExternalAnnotation(listOwner: PsiModifierListOwner, annotationFQN: String): 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")
}
@@ -38,11 +43,15 @@ class MockExternalAnnotationsManager : ExternalAnnotationsManager() {
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")
}
override fun hasAnnotationRootsForFile(file: VirtualFile): Boolean {
throw UnsupportedOperationException("not implemented")
}
}
}
@@ -29,4 +29,4 @@ class MockInferredAnnotationsManager : InferredAnnotationsManager() {
companion object {
val EMPTY_PSI_ANNOTATION_ARRAY = arrayOf<PsiAnnotation>()
}
}
}
@@ -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.impl.VirtualFileBoundJavaClass
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.incremental.IncrementalPackageFragmentProvider
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.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.storage.StorageManager
import java.util.*
import kotlin.reflect.KFunction1
@@ -75,16 +73,16 @@ object TopDownAnalyzerFacadeForJVM {
@JvmStatic
@JvmOverloads
fun analyzeFilesWithJavaIntegration(
project: Project,
files: Collection<KtFile>,
trace: BindingTrace,
configuration: CompilerConfiguration,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory = ::FileBasedDeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
project: Project,
files: Collection<KtFile>,
trace: BindingTrace,
configuration: CompilerConfiguration,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory = ::FileBasedDeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
): AnalysisResult {
val container = createContainer(
project, files, trace, configuration, packagePartProvider, declarationProviderFactory, sourceModuleSearchScope
project, files, trace, configuration, packagePartProvider, declarationProviderFactory, sourceModuleSearchScope
)
val module = container.get<ModuleDescriptor>()
@@ -118,13 +116,13 @@ object TopDownAnalyzerFacadeForJVM {
}
fun createContainer(
project: Project,
files: Collection<KtFile>,
trace: BindingTrace,
configuration: CompilerConfiguration,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
project: Project,
files: Collection<KtFile>,
trace: BindingTrace,
configuration: CompilerConfiguration,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
declarationProviderFactory: (StorageManager, Collection<KtFile>) -> DeclarationProviderFactory,
sourceModuleSearchScope: GlobalSearchScope = newModuleSearchScope(project, files)
): ComponentProvider {
val createBuiltInsFromModule = configuration.getBoolean(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES)
val moduleContext = createModuleContext(project, configuration, createBuiltInsFromModule)
@@ -146,12 +144,11 @@ object TopDownAnalyzerFacadeForJVM {
val languageVersionSettings = configuration.languageVersionSettings
val optionalBuiltInsModule =
if (configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)) {
if (createBuiltInsFromModule)
JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule
else module.builtIns.builtInsModule
}
else null
if (configuration.getBoolean(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES)) {
if (createBuiltInsFromModule)
JvmBuiltIns(storageManager).apply { initialize(module, languageVersionSettings) }.builtInsModule
else module.builtIns.builtInsModule
} else null
fun StorageComponentContainer.useJavac() {
useImpl<JavacBasedClassFinder>()
@@ -159,34 +156,38 @@ object TopDownAnalyzerFacadeForJVM {
useImpl<JavacBasedSourceElementFactory>()
}
@Suppress("USELESS_CAST")
val configureJavaClassFinder =
if (configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) StorageComponentContainer::useJavac
else null as KFunction1<StorageComponentContainer, Unit>?
if (configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) StorageComponentContainer::useJavac
else null as KFunction1<StorageComponentContainer, Unit>?
val dependencyModule = if (separateModules) {
val dependenciesContext = ContextForNewModule(
moduleContext, Name.special("<dependencies of ${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"),
module.builtIns, null
moduleContext, Name.special("<dependencies of ${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"),
module.builtIns, null
)
// Scope for the dependency module contains everything except files present in the scope for the source module
val dependencyScope = GlobalSearchScope.notScope(sourceScope)
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker, expectActualTracker,
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker, expectActualTracker,
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder
)
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get<JavaDescriptorResolver>()
moduleClassResolver.compiledCodeResolver = dependenciesContainer.get()
dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule))
dependenciesContext.initializeModuleContents(CompositePackageFragmentProvider(listOf(
moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>()
)))
dependenciesContext.initializeModuleContents(
CompositePackageFragmentProvider(
listOf(
moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>()
)
)
)
dependenciesContext.module
}
else null
} else null
val partProvider = packagePartProvider(sourceScope).let { fragment ->
if (targetIds == null || incrementalComponents == null) fragment
@@ -198,23 +199,22 @@ object TopDownAnalyzerFacadeForJVM {
// to be stored in CliLightClassGenerationSupport, and it better be the source one (otherwise light classes would not be found)
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
val container = createContainerForTopDownAnalyzerForJvm(
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker, expectActualTracker,
partProvider, moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder,
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker, expectActualTracker,
partProvider, moduleClassResolver, jvmTarget, languageVersionSettings, configureJavaClassFinder,
javaClassTracker = configuration[JVMConfigurationKeys.JAVA_CLASSES_TRACKER]
).apply {
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>()
if (incrementalComponents != null) {
targetIds?.mapTo(additionalProviders) { targetId ->
IncrementalPackageFragmentProvider(
files, module, storageManager, container.get<DeserializationComponentsForJava>().components,
incrementalComponents.getIncrementalCache(targetId), targetId,
container.get<KotlinClassFinder>()
files, module, storageManager, container.get<DeserializationComponentsForJava>().components,
incrementalComponents.getIncrementalCache(targetId), targetId, container.get()
)
}
}
@@ -228,13 +228,14 @@ object TopDownAnalyzerFacadeForJVM {
// TODO: remove dependencyModule from friends
module.setDependencies(
listOfNotNull(module, dependencyModule, optionalBuiltInsModule),
if (dependencyModule != null) setOf(dependencyModule) else emptySet()
listOfNotNull(module, dependencyModule, optionalBuiltInsModule),
if (dependencyModule != null) setOf(dependencyModule) else emptySet()
)
module.initialize(
CompositePackageFragmentProvider(
listOf(container.get<KotlinCodeAnalyzer>().packageFragmentProvider) + additionalProviders
)
)
module.initialize(CompositePackageFragmentProvider(
listOf(container.get<KotlinCodeAnalyzer>().packageFragmentProvider) +
additionalProviders
))
return container
}
@@ -251,7 +252,7 @@ object TopDownAnalyzerFacadeForJVM {
// 'isDirectory' check is needed because otherwise directories such as 'frontend.java' would be recognized
// as Java source files, which makes no sense
override fun contains(file: VirtualFile) =
file.fileType === JavaFileType.INSTANCE && !file.isDirectory
file.fileType === JavaFileType.INSTANCE && !file.isDirectory
override fun toString() = "All Java sources in the project"
}
@@ -270,20 +271,20 @@ object TopDownAnalyzerFacadeForJVM {
}
fun createContextWithSealedModule(project: Project, configuration: CompilerConfiguration): MutableModuleContext =
createModuleContext(project, configuration, false).apply {
setDependencies(module, module.builtIns.builtInsModule)
(module.builtIns as JvmBuiltIns).initialize(module, configuration.languageVersionSettings)
}
createModuleContext(project, configuration, false).apply {
setDependencies(module, module.builtIns.builtInsModule)
(module.builtIns as JvmBuiltIns).initialize(module, configuration.languageVersionSettings)
}
private fun createModuleContext(
project: Project,
configuration: CompilerConfiguration,
createBuiltInsFromModule: Boolean
project: Project,
configuration: CompilerConfiguration,
createBuiltInsFromModule: Boolean
): MutableModuleContext {
val projectContext = ProjectContext(project)
val builtIns = JvmBuiltIns(projectContext.storageManager, !createBuiltInsFromModule)
return ContextForNewModule(
projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null
projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null
).apply {
if (createBuiltInsFromModule) {
builtIns.builtInsModule = module
@@ -58,10 +58,10 @@ fun CompilerConfiguration.addJavaSourceRoots(files: List<File>, packagePrefix: S
}
val CompilerConfiguration.javaSourceRoots: Set<String>
get() = getList(JVMConfigurationKeys.CONTENT_ROOTS).mapNotNullTo(linkedSetOf<String>()) { root ->
when (root) {
is KotlinSourceRoot -> root.path
is JavaSourceRoot -> root.file.path
else -> null
}
}
get() = getList(JVMConfigurationKeys.CONTENT_ROOTS).mapNotNullTo(linkedSetOf()) { root ->
when (root) {
is KotlinSourceRoot -> root.path
is JavaSourceRoot -> root.file.path
else -> null
}
}
@@ -34,27 +34,27 @@ class JvmDependenciesDynamicCompoundIndex : JvmDependenciesIndex {
}
fun addNewIndexForRoots(roots: Iterable<JavaRoot>): JvmDependenciesIndex? =
lock.read {
val alreadyIndexed = indexedRoots.toHashSet()
val newRoots = roots.filter { root -> root !in alreadyIndexed }
if (newRoots.isEmpty()) null
else JvmDependenciesIndexImpl(newRoots).also(this::addIndex)
}
lock.read {
val alreadyIndexed = indexedRoots.toHashSet()
val newRoots = roots.filter { root -> root !in alreadyIndexed }
if (newRoots.isEmpty()) null
else JvmDependenciesIndexImpl(newRoots).also(this::addIndex)
}
override val indexedRoots: Sequence<JavaRoot> get() = indices.asSequence().flatMap { it.indexedRoots }
override fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T? = lock.read {
indices.asSequence().mapNotNull { it.findClass(classId, acceptedRootTypes, findClassGivenDirectory) }.firstOrNull()
}
override fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
) = lock.read {
indices.forEach { it.traverseDirectoriesInPackage(packageFqName, acceptedRootTypes, continueSearch) }
}
@@ -25,15 +25,15 @@ interface JvmDependenciesIndex {
val indexedRoots: Sequence<JavaRoot>
fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T?
fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType> = JavaRoot.SourceAndBinary,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
)
}
@@ -29,7 +29,7 @@ import java.util.*
// speeds up finding files/classes in classpath/java source roots
// 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
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
private val roots: List<JavaRoot> by lazy { _roots.toList() }
@@ -69,9 +69,9 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
}
override fun traverseDirectoriesInPackage(
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
packageFqName: FqName,
acceptedRootTypes: Set<JavaRoot.RootType>,
continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean
) {
search(TraverseRequest(packageFqName, acceptedRootTypes)) { dir, rootType ->
if (continueSearch(dir, rootType)) null else Unit
@@ -80,9 +80,9 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
// findClassGivenDirectory MUST check whether the class with this classId exists in given package
override fun <T : Any> findClass(
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
classId: ClassId,
acceptedRootTypes: Set<JavaRoot.RootType>,
findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T?
): T? {
// make a decision based on information saved from last class search
if (lastClassSearch?.first?.classId != classId) {
@@ -95,16 +95,14 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes
if (limitedRootTypes.isEmpty()) {
null
}
else {
} else {
search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory)
}
}
is SearchResult.Found -> {
if (cachedRequest.acceptedRootTypes == acceptedRootTypes) {
findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type)
}
else {
} else {
search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory)
}
}
@@ -151,11 +149,11 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
// try to find a target directory corresponding to package represented by packagesPath in a given root represented by index
// possibly filling "Cache" objects with new information
private fun travelPath(
rootIndex: Int,
packageFqName: FqName,
packagesPath: List<String>,
fillCachesAfter: Int,
cachesPath: List<Cache>
rootIndex: Int,
packageFqName: FqName,
packagesPath: List<String>,
fillCachesAfter: Int,
cachesPath: List<Cache>
): VirtualFile? {
if (rootIndex >= maxIndex) {
for (i in (fillCachesAfter + 1)..(cachesPath.size - 1)) {
@@ -184,8 +182,7 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
if (prefixPathSegments[pathIndex].identifier != subPackageName) {
return null
}
}
else {
} else {
currentFile = currentFile.findChildPackage(subPackageName, pathRoot.type) ?: return null
}
@@ -235,8 +232,8 @@ class JvmDependenciesIndexImpl(_roots: List<JavaRoot>): JvmDependenciesIndex {
}
private data class TraverseRequest(
override val packageFqName: FqName,
override val acceptedRootTypes: Set<JavaRoot.RootType>
override val packageFqName: FqName,
override val acceptedRootTypes: Set<JavaRoot.RootType>
) : SearchRequest
private interface SearchRequest {
@@ -35,12 +35,12 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
private val classIdsInRoots = ArrayList<List<ClassId>>(roots.size)
fun findJavaSourceClass(classId: ClassId): VirtualFile? =
roots.indices
.find { index -> classId in getClassIdsForRootAt(index) }
?.let { index -> roots[index].file }
roots.indices
.find { index -> classId in getClassIdsForRootAt(index) }
?.let { index -> roots[index].file }
fun findJavaSourceClasses(packageFqName: FqName): List<ClassId> =
roots.indices.flatMap(this::getClassIdsForRootAt).filter { root -> root.packageFqName == packageFqName }
roots.indices.flatMap(this::getClassIdsForRootAt).filter { root -> root.packageFqName == packageFqName }
private fun getClassIdsForRootAt(index: Int): List<ClassId> {
for (i in classIdsInRoots.size..index) {
@@ -73,7 +73,7 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
private fun tokenText(): String = lexer.tokenText
private fun atClass(): Boolean =
braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS
braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS
fun readClassIds(): List<ClassId> {
var packageFqName = FqName.ROOT
@@ -25,10 +25,10 @@ import java.io.PrintWriter
import java.io.Writer
class JavacLogger(
context: Context,
errorWriter: PrintWriter,
warningWriter: PrintWriter,
infoWriter: PrintWriter
context: Context,
errorWriter: PrintWriter,
warningWriter: PrintWriter,
infoWriter: PrintWriter
) : Log(context, errorWriter, warningWriter, infoWriter) {
init {
context.put(Log.outKey, infoWriter)
@@ -39,18 +39,20 @@ class JavacLogger(
companion object {
fun preRegister(context: Context, messageCollector: MessageCollector) {
context.put(Log.logKey, Context.Factory<Log> {
JavacLogger(it,
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO)))
JavacLogger(
it,
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)),
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO))
)
})
}
}
}
private class MessageCollectorAdapter(
private val messageCollector: MessageCollector,
private val severity: CompilerMessageSeverity
private val messageCollector: MessageCollector,
private val severity: CompilerMessageSeverity
) : Writer() {
override fun write(buffer: CharArray, offset: Int, length: Int) {
if (length == 1 && buffer[0] == '\n') return
@@ -38,9 +38,10 @@ class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: Li
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
.mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.classId }
.mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.classId }
supersCache[classOrObject] = classIds
return classIds
@@ -49,12 +50,12 @@ class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: Li
override fun findField(classOrObject: KtClassOrObject, name: String): JavaField? {
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? {
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,25 +29,23 @@ import org.jetbrains.kotlin.psi.KtFile
import java.io.File
object JavacWrapperRegistrar {
private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context"
fun registerJavac(
project: MockProject,
configuration: CompilerConfiguration,
javaFiles: List<File>,
kotlinFiles: List<KtFile>,
arguments: Array<String>?,
bootClasspath: List<File>?,
sourcePath: List<File>?,
lightClassGenerationSupport: LightClassGenerationSupport
project: MockProject,
configuration: CompilerConfiguration,
javaFiles: List<File>,
kotlinFiles: List<KtFile>,
arguments: Array<String>?,
bootClasspath: List<File>?,
sourcePath: List<File>?,
lightClassGenerationSupport: LightClassGenerationSupport
): Boolean {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
try {
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)")
return false
}
@@ -60,8 +58,10 @@ object JavacWrapperRegistrar {
val compileJava = configuration.getBoolean(JVMConfigurationKeys.COMPILE_JAVA)
val kotlinSupertypesResolver = JavacWrapperKotlinResolverImpl(lightClassGenerationSupport)
val javacWrapper = JavacWrapper(javaFiles, kotlinFiles, arguments, jvmClasspathRoots, bootClasspath, sourcePath,
kotlinSupertypesResolver, compileJava, outputDirectory, context)
val javacWrapper = JavacWrapper(
javaFiles, kotlinFiles, arguments, jvmClasspathRoots, bootClasspath, sourcePath,
kotlinSupertypesResolver, compileJava, outputDirectory, context
)
project.registerService(JavacWrapper::class.java, javacWrapper)
@@ -37,7 +37,7 @@ class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule)
override fun findModule(name: String): JavaModule? =
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
val file = moduleRoot.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE) ?: return null
@@ -35,7 +35,7 @@ class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule)
override fun findModule(name: String): JavaModule? =
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
/*
@@ -35,7 +35,7 @@ class CliJavaModuleFinder(jrtFileSystemRoot: VirtualFile?) : JavaModuleFinder {
get() = modulesRoot?.children.orEmpty().asSequence().mapNotNull(this::findSystemModule)
override fun findModule(name: String): JavaModule? =
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
modulesRoot?.findChild(name)?.let(this::findSystemModule) ?: userModules[name]
private fun findSystemModule(moduleRoot: VirtualFile): JavaModule.Explicit? {
/*
@@ -27,9 +27,9 @@ import org.jetbrains.kotlin.resolve.jvm.modules.JavaModule
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
class CliJavaModuleResolver(
private val moduleGraph: JavaModuleGraph,
private val userModules: List<JavaModule>,
private val systemModules: List<JavaModule.Explicit>
private val moduleGraph: JavaModuleGraph,
private val userModules: List<JavaModule>,
private val systemModules: List<JavaModule.Explicit>
) : JavaModuleResolver {
init {
assert(userModules.count(JavaModule::isSourceModule) <= 1) {
@@ -52,10 +52,10 @@ class CliJavaModuleResolver(
}
private operator fun JavaModule.contains(file: VirtualFile): Boolean =
moduleRoots.any { (root, isBinary) -> isBinary && VfsUtilCore.isAncestor(root, file, false) }
moduleRoots.any { (root, isBinary) -> isBinary && VfsUtilCore.isAncestor(root, file, false) }
override fun checkAccessibility(
fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName?
fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName?
): JavaModuleResolver.AccessError? {
val ourModule = fileFromOurModule?.let(this::findJavaModule)
val theirModule = this.findJavaModule(referencedFile)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.modules
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
@@ -47,9 +46,9 @@ class CoreJrtFileSystem : DeprecatedVirtualFileSystem() {
}
internal class CoreJrtHandler(
val virtualFileSystem: CoreJrtFileSystem,
val jdkHomePath: String,
private val root: Path
val virtualFileSystem: CoreJrtFileSystem,
val jdkHomePath: String,
private val root: Path
) {
fun findFile(fileName: String): VirtualFile? {
val path = root.resolve(fileName)
@@ -80,9 +79,9 @@ class CoreJrtFileSystem : DeprecatedVirtualFileSystem() {
companion object {
private fun loadJrtFsJar(jdkHome: File): File? =
File(jdkHome, "lib/jrt-fs.jar").takeIf(File::exists)
File(jdkHome, "lib/jrt-fs.jar").takeIf(File::exists)
fun isModularJdk(jdkHome: File): Boolean =
loadJrtFsJar(jdkHome) != null
loadJrtFsJar(jdkHome) != null
}
}
@@ -36,10 +36,10 @@ internal class CoreJrtVirtualFile(private val handler: CoreJrtHandler, private v
override fun getFileSystem(): VirtualFileSystem = handler.virtualFileSystem
override fun getName(): String =
path.fileName.toString()
path.fileName.toString()
override fun getPath(): String =
FileUtil.toSystemIndependentName(handler.jdkHomePath + URLUtil.JAR_SEPARATOR + path)
FileUtil.toSystemIndependentName(handler.jdkHomePath + URLUtil.JAR_SEPARATOR + path)
override fun isWritable(): Boolean = false
@@ -55,8 +55,7 @@ internal class CoreJrtVirtualFile(private val handler: CoreJrtHandler, private v
override fun getChildren(): Array<out VirtualFile> {
val paths = try {
Files.newDirectoryStream(path).use(Iterable<Path>::toList)
}
catch (e: IOException) {
} catch (e: IOException) {
emptyList<Path>()
}
return when {
@@ -66,26 +65,26 @@ internal class CoreJrtVirtualFile(private val handler: CoreJrtHandler, private v
}
override fun getOutputStream(requestor: Any, newModificationStamp: Long, newTimeStamp: Long): OutputStream =
throw UnsupportedOperationException()
throw UnsupportedOperationException()
override fun contentsToByteArray(): ByteArray =
Files.readAllBytes(path)
Files.readAllBytes(path)
override fun getTimeStamp(): Long =
attributes.lastModifiedTime().toMillis()
attributes.lastModifiedTime().toMillis()
override fun getLength(): Long = attributes.size()
override fun refresh(asynchronous: Boolean, recursive: Boolean, postRunnable: Runnable?) {}
override fun getInputStream(): InputStream =
VfsUtilCore.inputStreamSkippingBOM(Files.newInputStream(path).buffered(), this)
VfsUtilCore.inputStreamSkippingBOM(Files.newInputStream(path).buffered(), this)
override fun getModificationStamp(): Long = 0
override fun equals(other: Any?): Boolean =
other is CoreJrtVirtualFile && path == other.path && fileSystem == other.fileSystem
other is CoreJrtVirtualFile && path == other.path && fileSystem == other.fileSystem
override fun hashCode(): Int =
path.hashCode()
path.hashCode()
}
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
class JavaModuleGraph(finder: JavaModuleFinder) {
private val module: (String) -> JavaModule? =
LockBasedStorageManager.NO_LOCKS.createMemoizedFunctionWithNullableValues(finder::findModule)
LockBasedStorageManager.NO_LOCKS.createMemoizedFunctionWithNullableValues(finder::findModule)
fun getAllDependencies(moduleNames: List<String>): LinkedHashSet<String> {
val visited = LinkedHashSet(moduleNames)
@@ -26,32 +26,31 @@ import org.jetbrains.kotlin.cli.jvm.BundledCompilerPlugins
import org.jetbrains.kotlin.compiler.plugin.*
import org.jetbrains.kotlin.config.CompilerConfiguration
import java.io.File
import java.net.URL
import java.util.*
object PluginCliParser {
@JvmStatic
fun loadPluginsSafe(pluginClasspaths: Array<String>?, pluginOptions: Array<String>?, configuration: CompilerConfiguration): ExitCode =
loadPluginsSafe(pluginClasspaths?.asIterable(), pluginOptions?.asIterable(), configuration)
@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)
try {
PluginCliParser.loadPlugins(pluginClasspaths, pluginOptions, configuration)
}
catch (e: PluginCliOptionProcessingException) {
} catch (e: PluginCliOptionProcessingException) {
val message = e.message + "\n\n" + cliPluginUsageString(e.pluginId, e.options)
messageCollector.report(CompilerMessageSeverity.ERROR, message)
return ExitCode.INTERNAL_ERROR
}
catch (e: CliOptionProcessingException) {
} catch (e: CliOptionProcessingException) {
messageCollector.report(CompilerMessageSeverity.ERROR, e.message!!)
return ExitCode.INTERNAL_ERROR
}
catch (t: Throwable) {
} catch (t: Throwable) {
MessageCollectorUtil.reportException(messageCollector, t)
return ExitCode.INTERNAL_ERROR
}
@@ -61,11 +60,11 @@ object PluginCliParser {
@JvmStatic
fun loadPlugins(pluginClasspaths: Iterable<String>?, pluginOptions: Iterable<String>?, configuration: CompilerConfiguration) {
val classLoader = PluginURLClassLoader(
pluginClasspaths
?.map { File(it).toURI().toURL() }
?.toTypedArray()
?: arrayOf<URL>(),
this::class.java.classLoader
pluginClasspaths
?.map { File(it).toURI().toURL() }
?.toTypedArray()
?: emptyArray(),
this::class.java.classLoader
)
val componentRegistrars = ServiceLoader.load(ComponentRegistrar::class.java, classLoader).toMutableList()
@@ -76,9 +75,9 @@ object PluginCliParser {
}
private fun processPluginOptions(
pluginOptions: Iterable<String>?,
configuration: CompilerConfiguration,
classLoader: ClassLoader
pluginOptions: Iterable<String>?,
configuration: CompilerConfiguration,
classLoader: ClassLoader
) {
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
@@ -94,7 +93,7 @@ object PluginCliParser {
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
val option = declaredOptions[optionValue!!.optionName]
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
optionsToValues.putValue(option, optionValue)
}
@@ -102,15 +101,17 @@ object PluginCliParser {
val values = optionsToValues[option]
if (option.required && values.isEmpty()) {
throw PluginCliOptionProcessingException(
processor.pluginId,
processor.pluginOptions,
"Required plugin option not present: ${processor.pluginId}:${option.name}")
processor.pluginId,
processor.pluginOptions,
"Required plugin option not present: ${processor.pluginId}:${option.name}"
)
}
if (!option.allowMultipleOccurrences && values.size > 1) {
throw PluginCliOptionProcessingException(
processor.pluginId,
processor.pluginOptions,
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.name}")
processor.pluginId,
processor.pluginOptions,
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.name}"
)
}
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<*> {
return try {
childClassLoader.findClass(name)
}
catch (e: ClassNotFoundException) {
} catch (e: ClassNotFoundException) {
super.loadClass(name, resolve)
}
}
@@ -45,8 +44,7 @@ internal class PluginURLClassLoader(urls: Array<URL>, parent: ClassLoader) : Cla
return try {
super.findClass(name)
}
catch (e: ClassNotFoundException) {
} catch (e: ClassNotFoundException) {
onFail.loadClass(name)
}
}
@@ -31,15 +31,17 @@ open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberD
override fun containsFile(file: KtFile) = delegate.containsFile(file)
override fun getDeclarations(kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean) = delegate.getDeclarations(kindFilter, nameFilter)
override fun getDeclarations(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean
) = delegate.getDeclarations(kindFilter, nameFilter)
override fun getFunctionDeclarations(name: Name) = delegate.getFunctionDeclarations(name)
override fun getPropertyDeclarations(name: Name) = delegate.getPropertyDeclarations(name)
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> =
delegate.getDestructuringDeclarationsEntries(name)
delegate.getDestructuringDeclarationsEntries(name)
override fun getClassOrObjectDeclarations(name: Name) = delegate.getClassOrObjectDeclarations(name)
@@ -43,26 +43,28 @@ class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : Ba
}
private fun checkConsistent(removedCompiledLines: Iterable<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) {
removedCompiledLines.zip(removedAnalyzedLines).forEach {
if (it.first != LineId(it.second)) {
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}")
removedCompiledLines.zip(removedAnalyzedLines).forEach { (removedCompiledLine, removedAnalyzedLine) ->
if (removedCompiledLine != LineId(removedAnalyzedLine)) {
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
class LineState(
val codeLine: ReplCodeLine,
val psiFile: KtFile,
val errorHolder: DiagnosticMessageHolder)
val codeLine: ReplCodeLine,
val psiFile: KtFile,
val errorHolder: DiagnosticMessageHolder
)
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)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.repl
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.CharsetToolkit
@@ -42,10 +41,10 @@ import kotlin.concurrent.write
const val KOTLIN_REPL_JVM_TARGET_PROPERTY = "kotlin.repl.jvm.target"
open class GenericReplChecker(
disposable: Disposable,
private val scriptDefinition: KotlinScriptDefinition,
private val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
disposable: Disposable,
private val scriptDefinition: KotlinScriptDefinition,
private val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : ReplCheckAction {
internal val environment = run {
@@ -57,7 +56,7 @@ open class GenericReplChecker(
if (get(JVMConfigurationKeys.JVM_TARGET) == null) {
put(JVMConfigurationKeys.JVM_TARGET,
System.getProperty(KOTLIN_REPL_JVM_TARGET_PROPERTY)?.let { JvmTarget.fromString(it) }
?: if (getJavaVersion() >= 0x10008) JvmTarget.JVM_1_8 else JvmTarget.JVM_1_6)
?: if (getJavaVersion() >= 0x10008) JvmTarget.JVM_1_8 else JvmTarget.JVM_1_6)
}
}
KotlinCoreEnvironment.createForProduction(disposable, compilerConfiguration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
@@ -72,11 +71,15 @@ open class GenericReplChecker(
val checkerState = state.asState(GenericReplCheckerState::class.java)
val scriptFileName = makeScriptBaseName(codeLine)
val virtualFile =
LightVirtualFile("$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, StringUtil.convertLineSeparators(codeLine.code)).apply {
charset = CharsetToolkit.UTF8_CHARSET
}
LightVirtualFile(
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
KotlinLanguage.INSTANCE,
StringUtil.convertLineSeparators(codeLine.code)
).apply {
charset = CharsetToolkit.UTF8_CHARSET
}
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
?: error("Script file not analyzed at line ${codeLine.no}: ${codeLine.code}")
?: error("Script file not analyzed at line ${codeLine.no}: ${codeLine.code}")
val errorHolder = createDiagnosticHolder()
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.cli.jvm.repl
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
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.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -41,14 +41,18 @@ import kotlin.concurrent.write
// WARNING: not thread safe, assuming external synchronization
open class GenericReplCompiler(disposable: Disposable,
scriptDefinition: KotlinScriptDefinition,
private val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
open class GenericReplCompiler(
disposable: Disposable,
scriptDefinition: KotlinScriptDefinition,
private val compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : ReplCompiler {
constructor(scriptDefinition: KotlinScriptDefinition, compilerConfiguration: CompilerConfiguration, messageCollector: MessageCollector) :
this(Disposer.newDisposable(), scriptDefinition, compilerConfiguration, messageCollector)
constructor(
scriptDefinition: KotlinScriptDefinition,
compilerConfiguration: CompilerConfiguration,
messageCollector: MessageCollector
) : this(Disposer.newDisposable(), scriptDefinition, compilerConfiguration, messageCollector)
private val checker = GenericReplChecker(disposable, scriptDefinition, compilerConfiguration, messageCollector)
@@ -66,7 +70,8 @@ open class GenericReplCompiler(disposable: Disposable,
when (res) {
is ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete()
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)
@@ -88,29 +93,28 @@ open class GenericReplCompiler(disposable: Disposable,
}
val generationState = GenerationState.Builder(
psiFile.project,
ClassBuilderFactories.BINARIES,
compilerState.analyzerEngine.module,
compilerState.analyzerEngine.trace.bindingContext,
listOf(psiFile),
compilerConfiguration
psiFile.project,
ClassBuilderFactories.BINARIES,
compilerState.analyzerEngine.module,
compilerState.analyzerEngine.trace.bindingContext,
listOf(psiFile),
compilerConfiguration
).build()
generationState.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
generationState.replSpecific.earlierScriptsForReplInterpreter = compilerState.history.map { it.item }
generationState.beforeCompile()
KotlinCodegenFacade.generatePackage(
generationState,
psiFile.script!!.containingKtFile.packageFqName,
setOf(psiFile.script!!.containingKtFile),
org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION)
generationState,
psiFile.script!!.containingKtFile.packageFqName,
setOf(psiFile.script!!.containingKtFile),
CompilationErrorHandler.THROW_EXCEPTION
)
val generatedClassname = makeScriptBaseName(codeLine)
compilerState.history.push(LineId(codeLine), scriptDescriptor)
val expression = psiFile.getChildOfType<KtScript>()?.
getChildOfType<KtBlockExpression>()?.
getChildOfType<KtScriptInitializer>()?.
getChildOfType<KtExpression>()
val expression = psiFile.getChildOfType<KtScript>()?.getChildOfType<KtBlockExpression>()?.getChildOfType<KtScriptInitializer>()
?.getChildOfType<KtExpression>()
val type = expression?.let {
compilerState.analyzerEngine.trace.bindingContext.getType(it)
@@ -118,17 +122,19 @@ open class GenericReplCompiler(disposable: Disposable,
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)
}
return ReplCompileResult.CompiledClasses(LineId(codeLine),
compilerState.history.map { it.id },
generatedClassname,
generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
generationState.replSpecific.hasResult,
classpathAddendum ?: emptyList(),
type)
return ReplCompileResult.CompiledClasses(
LineId(codeLine),
compilerState.history.map { it.id },
generatedClassname,
generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
generationState.replSpecific.hasResult,
classpathAddendum ?: emptyList(),
type
)
}
}
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
class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
private val topDownAnalysisContext: TopDownAnalysisContext
private val topDownAnalyzer: LazyTopDownAnalyzer
private val resolveSession: ResolveSession
@@ -63,28 +62,29 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
// to be found via ResolveSession. The latter is true as long as light classes are not needed in REPL (which is currently true
// because no symbol declared in the REPL session can be used from Java)
val container = TopDownAnalyzerFacadeForJVM.createContainer(
environment.project,
emptyList(),
trace,
environment.configuration,
environment::createPackagePartProvider,
{ _, _ -> ScriptMutableDeclarationProviderFactory() }
environment.project,
emptyList(),
trace,
environment.configuration,
environment::createPackagePartProvider,
{ _, _ -> ScriptMutableDeclarationProviderFactory() }
)
this.module = container.get<ModuleDescriptorImpl>()
this.scriptDeclarationFactory = container.get<ScriptMutableDeclarationProviderFactory>()
this.resolveSession = container.get<ResolveSession>()
this.module = container.get()
this.scriptDeclarationFactory = container.get()
this.resolveSession = container.get()
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 {
val scriptDescriptor: ScriptDescriptor?
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 {
override val scriptDescriptor: ScriptDescriptor? get() = null
@@ -115,8 +115,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
return if (hasErrors) {
replState.lineFailure(linePsi, codeLine)
ReplLineAnalysisResult.WithErrors(diagnostics)
}
else {
} else {
val scriptDescriptor = context.scripts[linePsi.script]!!
replState.lineSuccess(linePsi, codeLine, scriptDescriptor)
ReplLineAnalysisResult.Successful(scriptDescriptor, diagnostics)
@@ -134,8 +133,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
val provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT)!!
try {
rootPackageProvider.addDelegateProvider(provider)
}
catch (e: UninitializedPropertyAccessException) {
} catch (e: UninitializedPropertyAccessException) {
rootPackageProvider = AdaptablePackageMemberDeclarationProvider(provider)
}
}
@@ -157,7 +155,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
}
class AdaptablePackageMemberDeclarationProvider(
private var delegateProvider: PackageMemberDeclarationProvider
private var delegateProvider: PackageMemberDeclarationProvider
) : DelegatePackageMemberDeclarationProvider(delegateProvider) {
fun addDelegateProvider(provider: PackageMemberDeclarationProvider) {
delegateProvider = CombinedPackageMemberDeclarationProvider(listOf(provider, delegateProvider))
@@ -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: review it's place in the extracted state infrastruct (now the analyzer itself is a part of the state
// TODO: merge with org.jetbrains.kotlin.resolve.repl.ReplState when switching to new REPL infrastructure everywhere
// TODO: review its place in the extracted state infrastructure (now the analyzer itself is a part of the state)
class ResettableAnalyzerState {
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
private val submittedLines = hashMapOf<KtFile, LineInfo>()
@@ -212,7 +210,12 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
abstract val parentLine: SuccessfulLine?
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()
}
@@ -39,4 +39,4 @@ class IdeReplExceptionReporter(private val replWriter: ReplWriter) : ReplExcepti
replWriter.sendInternalErrorReport(internalErrorText)
}
}
}
@@ -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.repl.ReplEvalResult
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.ReplConfiguration
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.KotlinCompilerVersion
@@ -36,9 +36,9 @@ import java.util.concurrent.Executors
import java.util.concurrent.Future
class ReplFromTerminal(
disposable: Disposable,
compilerConfiguration: CompilerConfiguration,
private val replConfiguration: ReplConfiguration
disposable: Disposable,
compilerConfiguration: CompilerConfiguration,
private val replConfiguration: ReplConfiguration
) {
private val replInitializer: Future<ReplInterpreter> = Executors.newSingleThreadExecutor().submit(Callable {
ReplInterpreter(disposable, compilerConfiguration, replConfiguration)
@@ -53,9 +53,11 @@ class ReplFromTerminal(
private fun doRun() {
try {
with (writer) {
printlnWelcomeMessage("Welcome to Kotlin version ${KotlinCompilerVersion.VERSION} " +
"(JRE ${System.getProperty("java.runtime.version")})")
with(writer) {
printlnWelcomeMessage(
"Welcome to Kotlin version ${KotlinCompilerVersion.VERSION} " +
"(JRE ${System.getProperty("java.runtime.version")})"
)
printlnWelcomeMessage("Type :help for help, :quit for quit")
}
@@ -71,16 +73,13 @@ class ReplFromTerminal(
break
}
}
}
catch (e: Exception) {
} catch (e: Exception) {
replConfiguration.exceptionReporter.report(e)
throw e
}
finally {
} finally {
try {
replConfiguration.commandReader.flushHistory()
}
catch (e: Exception) {
} catch (e: Exception) {
replConfiguration.exceptionReporter.report(e)
throw e
}
@@ -99,7 +98,7 @@ class ReplFromTerminal(
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))
return if (notQuit) WhatNextAfterOneLine.READ_LINE else WhatNextAfterOneLine.QUIT
}
@@ -107,8 +106,7 @@ class ReplFromTerminal(
val lineResult = eval(line)
return if (lineResult is ReplEvalResult.Incomplete) {
WhatNextAfterOneLine.INCOMPLETE
}
else {
} else {
WhatNextAfterOneLine.READ_LINE
}
}
@@ -132,22 +130,21 @@ class ReplFromTerminal(
@Throws(Exception::class)
private fun oneCommand(command: String): Boolean {
val split = splitCommand(command)
if (split.size >= 1 && command == "help") {
writer.printlnHelpMessage("Available commands:\n" +
":help show this help\n" +
":quit exit the interpreter\n" +
":dump bytecode dump classes to terminal\n" +
":load <file> load script from specified file")
if (split.isNotEmpty() && command == "help") {
writer.printlnHelpMessage(
"Available commands:\n" +
":help show this help\n" +
":quit exit the interpreter\n" +
":dump bytecode dump classes to terminal\n" +
":load <file> load script from specified file"
)
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))
return true
}
else if (split.size >= 1 && split[0] == "quit") {
} else if (split.isNotEmpty() && split[0] == "quit") {
return false
}
else if (split.size >= 2 && split[0] == "load") {
} else if (split.size >= 2 && split[0] == "load") {
val fileName = split[1]
try {
val scriptText = FileUtil.loadFile(File(fileName))
@@ -156,8 +153,7 @@ class ReplFromTerminal(
writer.outputCompileError("Can not load script: ${e.message}")
}
return true
}
else {
} else {
writer.printlnHelpMessage("Unknown command\n" + "Type :help for help")
return true
}
@@ -173,12 +169,10 @@ class ReplFromTerminal(
val replConfiguration = if (replIdeMode) IdeReplConfiguration() else ConsoleReplConfiguration()
return try {
ReplFromTerminal(disposable, configuration, replConfiguration).doRun()
}
catch (e: Exception) {
} catch (e: Exception) {
replConfiguration.exceptionReporter.report(e)
throw e
}
}
}
}
}
@@ -33,9 +33,9 @@ import java.net.URLClassLoader
import java.util.concurrent.atomic.AtomicInteger
class ReplInterpreter(
disposable: Disposable,
private val configuration: CompilerConfiguration,
private val replConfiguration: ReplConfiguration
disposable: Disposable,
private val configuration: CompilerConfiguration,
private val replConfiguration: ReplConfiguration
) {
private val lineNumber = AtomicInteger()
@@ -60,14 +60,18 @@ class ReplInterpreter(
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
val msg = messageRenderer.render(severity, message, location).trimEnd()
with (replConfiguration.writer) {
with(replConfiguration.writer) {
when (severity) {
CompilerMessageSeverity.EXCEPTION -> sendInternalErrorReport(msg)
CompilerMessageSeverity.ERROR -> outputCompileError(msg)
CompilerMessageSeverity.STRONG_WARNING -> {} // TODO consider reporting this and two below
CompilerMessageSeverity.WARNING -> {}
CompilerMessageSeverity.INFO -> {}
else -> {}
CompilerMessageSeverity.STRONG_WARNING -> {
} // TODO consider reporting this and two below
CompilerMessageSeverity.WARNING -> {
}
CompilerMessageSeverity.INFO -> {
}
else -> {
}
}
}
}
@@ -86,14 +90,17 @@ class ReplInterpreter(
private val evalState by lazy { scriptEvaluator.createState() }
fun eval(line: String): ReplEvalResult {
val fullText = (previousIncompleteLines + line).joinToString(separator = "\n")
try {
val evalRes = scriptEvaluator.compileAndEval(evalState, ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText), null, object : InvokeWrapper {
override fun <T> invoke(body: () -> T): T = replConfiguration.executionInterceptor.execute(body)
})
val evalRes = scriptEvaluator.compileAndEval(
evalState,
ReplCodeLine(lineNumber.getAndIncrement(), 0, fullText),
null,
object : InvokeWrapper {
override fun <T> invoke(body: () -> T): T = replConfiguration.executionInterceptor.execute(body)
}
)
when {
evalRes !is ReplEvalResult.Incomplete -> previousIncompleteLines.clear()
@@ -101,8 +108,7 @@ class ReplInterpreter(
else -> return ReplEvalResult.Error.CompileTime("incomplete code")
}
return evalRes
}
catch (e: Throwable) {
} catch (e: Throwable) {
val writer = PrintWriter(System.err)
classLoader.dumpClasses(writer)
writer.flush()
@@ -36,4 +36,4 @@ class ConsoleReplConfiguration : ReplConfiguration {
get() = SnippetExecutionInterceptor
override fun createDiagnosticHolder() = ConsoleDiagnosticMessageHolder()
}
}
@@ -64,4 +64,4 @@ class IdeReplConfiguration : ReplConfiguration {
exceptionReporter = IdeReplExceptionReporter(writer)
commandReader = IdeReplCommandReader()
}
}
}
@@ -29,4 +29,4 @@ interface ReplConfiguration {
val executionInterceptor: SnippetExecutionInterceptor
fun createDiagnosticHolder(): DiagnosticMessageHolder
}
}
@@ -22,4 +22,4 @@ interface SnippetExecutionInterceptor {
companion object Plain : SnippetExecutionInterceptor {
override fun <T> execute(block: () -> T) = block()
}
}
}
@@ -27,8 +27,9 @@ class ConsoleDiagnosticMessageHolder : MessageCollectorBasedReporter, Diagnostic
private val outputStream = ByteArrayOutputStream()
override val messageCollector: GroupingMessageCollector = GroupingMessageCollector(
PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.WITHOUT_PATHS, false),
false)
PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.WITHOUT_PATHS, false),
false
)
override fun renderMessage(): String {
messageCollector.flush()
@@ -20,4 +20,4 @@ import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter
interface DiagnosticMessageHolder : DiagnosticMessageReporter {
fun renderMessage(): String
}
}
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.cli.jvm.repl.messages
import com.intellij.openapi.util.text.StringUtil
// using '#' to avoid collisions with xml escaping
internal val SOURCE_CHARS: Array<String> = arrayOf("\n", "#")
internal val SOURCE_CHARS: Array<String> = arrayOf("\n", "#")
internal val XML_REPLACEMENTS: Array<String> = arrayOf("#n", "#diez")
fun unescapeLineBreaks(s: String) = StringUtil.replace(s, XML_REPLACEMENTS, SOURCE_CHARS)
fun unescapeLineBreaks(s: String) = StringUtil.replace(s, XML_REPLACEMENTS, SOURCE_CHARS)
@@ -28,26 +28,24 @@ import java.util.logging.Logger
class ConsoleReplCommandReader : ReplCommandReader {
private val lineReader = LineReaderBuilder.builder()
.appName("kotlin")
.terminal(TerminalBuilder.terminal())
.variable(LineReader.HISTORY_FILE, File(File(System.getProperty("user.home")), ".kotlinc_history").absolutePath)
.build()
.apply {
setOpt(LineReader.Option.DISABLE_EVENT_EXPANSION)
}
.appName("kotlin")
.terminal(TerminalBuilder.terminal())
.variable(LineReader.HISTORY_FILE, File(File(System.getProperty("user.home")), ".kotlinc_history").absolutePath)
.build()
.apply {
setOpt(LineReader.Option.DISABLE_EVENT_EXPANSION)
}
override fun readLine(next: ReplFromTerminal.WhatNextAfterOneLine): String? {
val prompt = if (next == ReplFromTerminal.WhatNextAfterOneLine.INCOMPLETE) "... " else ">>> "
try {
return lineReader.readLine(prompt)
}
catch (e: UserInterruptException) {
return try {
lineReader.readLine(prompt)
} catch (e: UserInterruptException) {
println("<interrupted>")
System.out.flush()
return ""
}
catch (e: EndOfFileException) {
return null
""
} catch (e: EndOfFileException) {
null
}
}
@@ -55,7 +53,7 @@ class ConsoleReplCommandReader : ReplCommandReader {
private companion object {
init {
Logger.getLogger("org.jline").level = Level.OFF;
Logger.getLogger("org.jline").level = Level.OFF
}
}
}
@@ -21,4 +21,4 @@ import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
class IdeReplCommandReader : ReplCommandReader {
override fun readLine(next: ReplFromTerminal.WhatNextAfterOneLine) = readLine()
override fun flushHistory() = Unit
}
}
@@ -21,4 +21,4 @@ import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal
interface ReplCommandReader {
fun readLine(next: ReplFromTerminal.WhatNextAfterOneLine): String?
fun flushHistory()
}
}
@@ -26,8 +26,8 @@ import java.io.InputStream
import javax.xml.parsers.DocumentBuilderFactory
class ReplSystemInWrapper(
private val stdin: InputStream,
private val replWriter: ReplWriter
private val stdin: InputStream,
private val replWriter: ReplWriter
) : InputStream() {
private var isXmlIncomplete = true
private var isLastByteProcessed = false
@@ -39,7 +39,8 @@ class ReplSystemInWrapper(
private val isAtBufferEnd: Boolean
get() = curBytePos == inputByteArray.size
@Volatile var isReplScriptExecuting = false
@Volatile
var isReplScriptExecuting = false
override fun read(): Int {
if (isLastByteProcessed) {
@@ -102,4 +103,4 @@ private fun parseXml(inputMessage: String): String {
val root = input.firstChild as Element
return root.textContent
}
}
@@ -60,4 +60,4 @@ class IdeSystemOutWrapperReplWriter(standardOut: PrintStream) : PrintStream(stan
override fun outputCompileError(x: String) = printlnWithEscaping(x, COMPILE_ERROR)
override fun outputRuntimeError(x: String) = printlnWithEscaping(x, RUNTIME_ERROR)
override fun sendInternalErrorReport(x: String) = printlnWithEscaping(x, INTERNAL_ERROR)
}
}
@@ -27,4 +27,4 @@ interface ReplWriter {
fun outputCompileError(x: String)
fun outputRuntimeError(x: String)
fun sendInternalErrorReport(x: String)
}
}
@@ -43,16 +43,16 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
override fun createArguments() = K2MetadataCompilerArguments()
override fun setupPlatformSpecificArgumentsAndServices(
configuration: CompilerConfiguration, arguments: K2MetadataCompilerArguments, services: Services
configuration: CompilerConfiguration, arguments: K2MetadataCompilerArguments, services: Services
) {
// No specific arguments yet
}
override fun doExecute(
arguments: K2MetadataCompilerArguments,
configuration: CompilerConfiguration,
rootDisposable: Disposable,
paths: KotlinPaths?
arguments: K2MetadataCompilerArguments,
configuration: CompilerConfiguration,
rootDisposable: Disposable,
paths: KotlinPaths?
): ExitCode {
val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
@@ -74,12 +74,16 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
if (destination != null) {
if (destination.endsWith(".jar")) {
// 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))
}
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 (arguments.version) {
@@ -95,8 +99,7 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
val metadataVersion =
configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? BuiltInsBinaryVersion ?: BuiltInsBinaryVersion.INSTANCE
MetadataSerializer(metadataVersion, true).serialize(environment)
}
catch (e: CompilationException) {
} catch (e: CompilationException) {
collector.report(EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element))
return ExitCode.INTERNAL_ERROR
}
@@ -81,7 +81,7 @@ open class MetadataSerializer(
}
protected open fun performSerialization(
files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File
files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File
) {
val packageTable = hashMapOf<FqName, PackageParts>()
@@ -91,23 +91,29 @@ open class MetadataSerializer(
for (declaration in file.declarations) {
declaration.accept(object : KtVisitorVoid() {
override fun visitNamedFunction(function: KtNamedFunction) {
members.add(bindingContext.get(BindingContext.FUNCTION, function)
?: error("No descriptor found for function ${function.fqName}"))
members.add(
bindingContext.get(BindingContext.FUNCTION, function)
?: error("No descriptor found for function ${function.fqName}")
)
}
override fun visitProperty(property: KtProperty) {
members.add(bindingContext.get(BindingContext.VARIABLE, property)
?: error("No descriptor found for property ${property.fqName}"))
members.add(
bindingContext.get(BindingContext.VARIABLE, property)
?: error("No descriptor found for property ${property.fqName}")
)
}
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
members.add(bindingContext.get(BindingContext.TYPE_ALIAS, typeAlias)
?: error("No descriptor found for type alias ${typeAlias.fqName}"))
members.add(
bindingContext.get(BindingContext.TYPE_ALIAS, typeAlias)
?: error("No descriptor found for type alias ${typeAlias.fqName}")
)
}
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject)
?: error("No descriptor found for class ${classOrObject.fqName}")
?: error("No descriptor found for class ${classOrObject.fqName}")
val destFile = File(destDir, getClassFilePath(ClassId(packageFqName, classDescriptor.name)))
PackageSerializer(listOf(classDescriptor), emptyList(), packageFqName, destFile).run()
}
@@ -139,17 +145,17 @@ open class MetadataSerializer(
protected open fun createSerializerExtension(): KotlinSerializerExtensionBase = MetadataSerializerExtension(metadataVersion)
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
packageFqName.asString().replace('.', '/') + "/" +
PackagePartClassUtils.getFilePartShortName(fileName) + DOT_METADATA_FILE_EXTENSION
packageFqName.asString().replace('.', '/') + "/" +
PackagePartClassUtils.getFilePartShortName(fileName) + DOT_METADATA_FILE_EXTENSION
private fun getClassFilePath(classId: ClassId): String =
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
protected inner class PackageSerializer(
private val classes: Collection<DeclarationDescriptor>,
private val members: Collection<DeclarationDescriptor>,
private val packageFqName: FqName,
private val destFile: File
private val classes: Collection<DeclarationDescriptor>,
private val members: Collection<DeclarationDescriptor>,
private val packageFqName: FqName,
private val destFile: File
) {
private val proto = ProtoBuf.PackageFragment.newBuilder()
private val extension = createSerializerExtension()