KT-45777: Refactor RuntimeModuleData to support classpath snapshotting

We are working on a feature in the Kotlin Gradle plugin called
`kotlin.incremental.useClasspathSnapshot` to improve incremental
Kotlin compilation.

In this feature, we need to extract ABI information from a .class file.
If the .class file is a Kotlin class, this info can be found in the
class header data. But if the .class file is a Java class, this info is
not readily available.

The RuntimeModuleData class in the ':core:descriptors.runtime' project
can help with that: It uses reflection to generate `ClassDescriptor`s.

However, reflection requires a full classpath to work correctly, whereas
we want to generate a `ClassDescriptor` directly for each class file
(also, reflection is probably slow).

To address that, this commit refactors RuntimeModuleData so that it can
support a generic Kotlin/JavaClassFinder, which can be based on either
reflection or bytecode analysis. The existing code continues to use
reflection while the new feature will use bytecode analysis (e.g., using
the existing BinaryJavaClass).

Bug: KT-45777
Test: Existing tests should pass (this is a refactoring-only change)
This commit is contained in:
Hung Nguyen
2021-07-26 15:19:46 +01:00
committed by nataliya.valtman
parent 206457d9ff
commit 170184dce4
2 changed files with 60 additions and 29 deletions
@@ -17,14 +17,13 @@ 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.load.kotlin.*
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
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,
@@ -39,7 +38,7 @@ class PackageFragmentFromClassLoaderProviderExtension(
trace: BindingTrace,
moduleInfo: ModuleInfo?,
lookupTracker: LookupTracker
): PackageFragmentProvider? {
): PackageFragmentProvider {
val classLoader = classLoaderGetter(scriptCompilationConfiguration)
val reflectKotlinClassFinder = ReflectKotlinClassFinder(classLoader)
@@ -54,16 +53,17 @@ class PackageFragmentFromClassLoaderProviderExtension(
)
val lazyJavaPackageFragmentProvider =
makeLazyJavaPackageFragmentFromClassLoaderProvider(
classLoader, module, storageManager, notFoundClasses,
reflectKotlinClassFinder, deserializedDescriptorResolver, singleModuleClassResolver,
makeLazyJavaPackageFragmentProvider(
ReflectJavaClassFinder(classLoader), module, storageManager, notFoundClasses,
reflectKotlinClassFinder, deserializedDescriptorResolver,
RuntimeErrorReporter, RuntimeSourceElementFactory, singleModuleClassResolver,
packagePartProvider
)
val deserializationComponentsForJava =
makeDeserializationComponentsForJava(
module, storageManager, notFoundClasses, lazyJavaPackageFragmentProvider,
reflectKotlinClassFinder, deserializedDescriptorResolver
reflectKotlinClassFinder, deserializedDescriptorResolver, RuntimeErrorReporter
)
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)