Reformat module 'cli', fix warnings/inspections
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+34
-25
@@ -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))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,4 +48,4 @@ class CliScriptDefinitionProvider : LazyScriptDefinitionProvider() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-7
@@ -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()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+62
-62
@@ -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))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+49
-52
@@ -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))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+49
-52
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-9
@@ -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 }
|
||||
}
|
||||
|
||||
-4
@@ -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> {
|
||||
|
||||
+30
-41
@@ -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)) }
|
||||
|
||||
+30
-41
@@ -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)) }
|
||||
|
||||
+30
-41
@@ -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())
|
||||
}
|
||||
|
||||
+3
-4
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -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
|
||||
|
||||
+10
-14
@@ -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
|
||||
|
||||
+10
-14
@@ -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
|
||||
|
||||
+12
-3
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
+60
-59
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -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
|
||||
|
||||
+6
-5
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -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()
|
||||
|
||||
+1
-1
@@ -36,4 +36,4 @@ class ConsoleReplConfiguration : ReplConfiguration {
|
||||
get() = SnippetExecutionInterceptor
|
||||
|
||||
override fun createDiagnosticHolder() = ConsoleDiagnosticMessageHolder()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,4 +64,4 @@ class IdeReplConfiguration : ReplConfiguration {
|
||||
exceptionReporter = IdeReplExceptionReporter(writer)
|
||||
commandReader = IdeReplCommandReader()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,4 +29,4 @@ interface ReplConfiguration {
|
||||
|
||||
val executionInterceptor: SnippetExecutionInterceptor
|
||||
fun createDiagnosticHolder(): DiagnosticMessageHolder
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,4 +22,4 @@ interface SnippetExecutionInterceptor {
|
||||
companion object Plain : SnippetExecutionInterceptor {
|
||||
override fun <T> execute(block: () -> T) = block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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()
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+14
-16
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user