Implement resolve top-level functions and props from classloader

#KT-33892 fixed
This commit is contained in:
Ilya Chernikov
2019-09-30 15:50:43 +02:00
parent 7b93970ce2
commit 2219b950f1
13 changed files with 461 additions and 93 deletions
@@ -7,23 +7,29 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.impl
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.NotFoundClasses
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.runtime.components.*
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.components.JavaResolverCache
import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.jvm.ClassLoaderByConfiguration
import kotlin.script.experimental.jvm.util.classpathFromClassloader
class PackageFragmentFromClassLoaderProviderExtension(
val classLoaderGetter: ClassLoaderByConfiguration,
val scriptCompilationConfiguration: ScriptCompilationConfiguration
val scriptCompilationConfiguration: ScriptCompilationConfiguration,
val compilerConfiguration: CompilerConfiguration
) : PackageFragmentProviderExtension {
override fun getPackageFragmentProvider(
@@ -40,11 +46,18 @@ class PackageFragmentFromClassLoaderProviderExtension(
val deserializedDescriptorResolver = DeserializedDescriptorResolver()
val singleModuleClassResolver = SingleModuleClassResolver()
val notFoundClasses = NotFoundClasses(storageManager, module)
val packagePartProvider =
PackagePartFromClassLoaderProvider(
classLoader,
compilerConfiguration.languageVersionSettings,
compilerConfiguration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
)
val lazyJavaPackageFragmentProvider =
makeLazyJavaPackageFragmentFromClassLoaderProvider(
classLoader, module, storageManager, notFoundClasses,
reflectKotlinClassFinder, deserializedDescriptorResolver, singleModuleClassResolver
reflectKotlinClassFinder, deserializedDescriptorResolver, singleModuleClassResolver,
packagePartProvider
)
val deserializationComponentsForJava =
@@ -55,6 +68,9 @@ class PackageFragmentFromClassLoaderProviderExtension(
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, JavaResolverCache.EMPTY)
singleModuleClassResolver.resolver = javaDescriptorResolver
return lazyJavaPackageFragmentProvider
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.scripting.compiler.plugin.impl
import com.intellij.util.SmartList
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.tryLoadModuleMapping
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartProviderBase
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import kotlin.script.experimental.jvm.util.forAllMatchingFiles
class PackagePartFromClassLoaderProvider(
classLoader: ClassLoader,
languageVersionSettings: LanguageVersionSettings,
messageCollector: MessageCollector
) : JvmPackagePartProviderBase<String>() {
private val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
override val loadedModules: MutableList<ModuleMappingInfo<String>> = SmartList()
init {
classLoader.forAllMatchingFiles("META-INF/*.${ModuleMapping.MAPPING_FILE_EXT}") { name, stream ->
tryLoadModuleMapping(
{ stream.readBytes() }, name, name, deserializationConfiguration, messageCollector
)?.let {
val moduleName = name.removePrefix("META-INF/").removeSuffix(".${ModuleMapping.MAPPING_FILE_EXT}")
loadedModules.add(ModuleMappingInfo(name, it, moduleName))
}
}
}
}
@@ -132,6 +132,23 @@ private fun compileImpl(
}
}
internal fun registerPackageFragmetProvidersIfNeeded(
scriptCompilationConfiguration: ScriptCompilationConfiguration,
environment: KotlinCoreEnvironment
) {
scriptCompilationConfiguration[ScriptCompilationConfiguration.dependencies]?.forEach { dependency ->
if (dependency is JvmDependencyFromClassLoader) {
// TODO: consider implementing deduplication
PackageFragmentProviderExtension.registerExtension(
environment.project,
PackageFragmentFromClassLoaderProviderExtension(
dependency.classLoaderGetter, scriptCompilationConfiguration, environment.configuration
)
)
}
}
}
private fun doCompile(
context: SharedScriptCompilationContext,
script: SourceCode,
@@ -141,14 +158,7 @@ private fun doCompile(
getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration
): ResultWithDiagnostics<KJvmCompiledScript<Any>> {
context.baseScriptCompilationConfiguration[ScriptCompilationConfiguration.dependencies]?.forEach { dependency ->
if (dependency is JvmDependencyFromClassLoader) {
PackageFragmentProviderExtension.registerExtension(
context.environment.project,
PackageFragmentFromClassLoaderProviderExtension(dependency.classLoaderGetter, context.baseScriptCompilationConfiguration)
)
}
}
registerPackageFragmetProvidersIfNeeded(getScriptConfiguration(sourceFiles.first()), context.environment)
val analysisResult = analyze(sourceFiles, context.environment)