Avoid multiple subsequent reading of the same class-file in front-end
^KT-23466 Fixed
This commit is contained in:
@@ -22,7 +22,15 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface JavaClassFinder {
|
||||
fun findClass(classId: ClassId): JavaClass?
|
||||
data class Request(
|
||||
val classId: ClassId,
|
||||
@Suppress("ArrayInDataClass")
|
||||
val previouslyFoundClassFileContent: ByteArray? = null,
|
||||
val outerClass: JavaClass? = null
|
||||
)
|
||||
|
||||
fun findClass(request: Request): JavaClass?
|
||||
fun findClass(classId: ClassId): JavaClass? = findClass(Request(classId))
|
||||
|
||||
fun findPackage(fqName: FqName): JavaPackage?
|
||||
|
||||
|
||||
+6
-1
@@ -706,7 +706,12 @@ class LazyJavaClassMemberScope(
|
||||
)
|
||||
} else null
|
||||
} else {
|
||||
c.components.finder.findClass(ownerDescriptor.classId!!.createNestedClassId(name))?.let {
|
||||
c.components.finder.findClass(
|
||||
JavaClassFinder.Request(
|
||||
ownerDescriptor.classId!!.createNestedClassId(name),
|
||||
outerClass = jClass
|
||||
)
|
||||
)?.let {
|
||||
LazyJavaClassDescriptor(c, ownerDescriptor, it)
|
||||
.also(c.components.javaClassesTracker::reportClass)
|
||||
}
|
||||
|
||||
+16
-4
@@ -22,10 +22,12 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.alwaysTrue
|
||||
import java.util.*
|
||||
|
||||
@@ -51,12 +54,14 @@ class LazyJavaPackageScope(
|
||||
c.storageManager.createMemoizedFunctionWithNullableValues<FindClassRequest, ClassDescriptor> classByRequest@{ request ->
|
||||
val requestClassId = ClassId(ownerDescriptor.fqName, request.name)
|
||||
|
||||
val kotlinBinaryClass =
|
||||
val kotlinClassOrClassFileContent =
|
||||
// These branches should be semantically equal, but the first one could be faster
|
||||
if (request.javaClass != null)
|
||||
c.components.kotlinClassFinder.findKotlinClass(request.javaClass)
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(request.javaClass)
|
||||
else
|
||||
c.components.kotlinClassFinder.findKotlinClass(requestClassId)
|
||||
c.components.kotlinClassFinder.findKotlinClassOrContent(requestClassId)
|
||||
|
||||
val kotlinBinaryClass = kotlinClassOrClassFileContent?.toKotlinJvmBinaryClass()
|
||||
|
||||
val classId = kotlinBinaryClass?.classId
|
||||
// Nested/local classes can be found when running in CLI in case when request.name looks like 'Outer$Inner'
|
||||
@@ -69,7 +74,14 @@ class LazyJavaPackageScope(
|
||||
is KotlinClassLookupResult.Found -> kotlinResult.descriptor
|
||||
is KotlinClassLookupResult.SyntheticClass -> null
|
||||
is KotlinClassLookupResult.NotFound -> {
|
||||
val javaClass = request.javaClass ?: c.components.finder.findClass(requestClassId)
|
||||
val javaClass =
|
||||
request.javaClass ?: c.components.finder.findClass(
|
||||
JavaClassFinder.Request(
|
||||
requestClassId,
|
||||
kotlinClassOrClassFileContent?.safeAs<KotlinClassFinder.Result.ClassFileContent>()
|
||||
?.content
|
||||
)
|
||||
)
|
||||
|
||||
if (javaClass?.lightClassOriginKind == LightClassOriginKind.BINARY) {
|
||||
throw IllegalStateException(
|
||||
|
||||
@@ -21,7 +21,23 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.KotlinMetadataFinder
|
||||
|
||||
interface KotlinClassFinder : KotlinMetadataFinder {
|
||||
fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass?
|
||||
fun findKotlinClassOrContent(classId: ClassId): Result?
|
||||
|
||||
fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass?
|
||||
fun findKotlinClassOrContent(javaClass: JavaClass): Result?
|
||||
|
||||
fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? =
|
||||
findKotlinClassOrContent(classId)?.toKotlinJvmBinaryClass()
|
||||
|
||||
fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? =
|
||||
findKotlinClassOrContent(javaClass)?.toKotlinJvmBinaryClass()
|
||||
|
||||
sealed class Result {
|
||||
fun toKotlinJvmBinaryClass(): KotlinJvmBinaryClass? = (this as? KotlinClass)?.kotlinJvmBinaryClass
|
||||
|
||||
data class KotlinClass(val kotlinJvmBinaryClass: KotlinJvmBinaryClass) : Result()
|
||||
data class ClassFileContent(
|
||||
@Suppress("ArrayInDataClass")
|
||||
val content: ByteArray
|
||||
) : Result()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -25,7 +25,8 @@ import kotlin.reflect.jvm.internal.structure.ReflectJavaClass
|
||||
import kotlin.reflect.jvm.internal.structure.ReflectJavaPackage
|
||||
|
||||
class ReflectJavaClassFinder(private val classLoader: ClassLoader) : JavaClassFinder {
|
||||
override fun findClass(classId: ClassId): JavaClass? {
|
||||
override fun findClass(request: JavaClassFinder.Request): JavaClass? {
|
||||
val classId = request.classId
|
||||
val packageFqName = classId.packageFqName
|
||||
val relativeClassName = classId.relativeClassName.asString().replace('.', '$')
|
||||
val name =
|
||||
|
||||
+5
-5
@@ -18,19 +18,19 @@ package kotlin.reflect.jvm.internal.components
|
||||
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.InputStream
|
||||
|
||||
class ReflectKotlinClassFinder(private val classLoader: ClassLoader) : KotlinClassFinder {
|
||||
private fun findKotlinClass(fqName: String): KotlinJvmBinaryClass? {
|
||||
return classLoader.tryLoadClass(fqName)?.let { ReflectKotlinClass.create(it) }
|
||||
private fun findKotlinClass(fqName: String): KotlinClassFinder.Result? {
|
||||
return classLoader.tryLoadClass(fqName)?.let { ReflectKotlinClass.create(it) }?.let(::KotlinClass)
|
||||
}
|
||||
|
||||
override fun findKotlinClass(classId: ClassId) = findKotlinClass(classId.toRuntimeFqName())
|
||||
override fun findKotlinClassOrContent(classId: ClassId) = findKotlinClass(classId.toRuntimeFqName())
|
||||
|
||||
override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? {
|
||||
override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? {
|
||||
// TODO: go through javaClass's class loader
|
||||
return findKotlinClass(javaClass.fqName?.asString() ?: return null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user