Avoid multiple subsequent reading of the same class-file in front-end

^KT-23466 Fixed
This commit is contained in:
Denis Zharkov
2018-12-13 13:51:56 +03:00
parent bc61e5a3bc
commit f153d97f40
20 changed files with 148 additions and 64 deletions
@@ -28,6 +28,7 @@ import gnu.trove.THashSet
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
@@ -81,7 +82,10 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap()
private val signatureParsingComponent = BinaryClassSignatureParser()
override fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? {
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope)
override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? {
val (classId, classFileContentFromRequest, outerClassFromRequest) = request
val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null
if (useFastClassFilesReading && virtualFile.extension == "class") {
@@ -92,13 +96,20 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
// This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary
// When it become wrong because we introduce the modules into CLI, it's worth to consider
// having different KotlinCliJavaFileManagerImpl's for different modules
val classContent = virtualFile.contentsToByteArray()
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
classId.outerClassId?.let { outerClassId ->
val outerClass = findClass(outerClassId, searchScope)
return@getOrPut outerClass?.findInnerClass(classId.shortClassName)
val outerClass = outerClassFromRequest ?: findClass(outerClassId, searchScope)
return if (outerClass is BinaryJavaClass)
outerClass.findInnerClass(classId.shortClassName, classFileContentFromRequest)
else
outerClass?.findInnerClass(classId.shortClassName)
}
// Here, we assume the class is top-level
val classContent = classFileContentFromRequest ?: virtualFile.contentsToByteArray()
if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null
val resolver = ClassifierResolutionContext { findClass(it, allScope) }
BinaryJavaClass(
@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.java.symbols.JavaClassSymbol
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
@@ -38,7 +39,7 @@ class JavaSymbolProvider(val project: Project) : FirSymbolProvider {
override fun getSymbolByFqName(classId: ClassId): ConeSymbol? {
return classCache.lookupCacheOrCalculate(classId) {
val facade = KotlinJavaPsiFacade.getInstance(project)
val foundClass = facade.findClass(classId, allScope)
val foundClass = facade.findClass(JavaClassFinder.Request(classId), allScope)
foundClass?.let { javaClass -> JavaClassSymbol(javaClass) }
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaPackageImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
@@ -33,10 +32,10 @@ class JavaClassFinderImpl : AbstractJavaClassFinder() {
super.initialize(trace, codeAnalyzer)
}
override fun findClass(classId: ClassId): JavaClass? = javaFacade.findClass(classId, javaSearchScope)
override fun findClass(request: JavaClassFinder.Request): JavaClass? = javaFacade.findClass(request, javaSearchScope)
override fun findPackage(fqName: FqName) = javaFacade.findPackage(fqName.asString(), javaSearchScope)?.let { JavaPackageImpl(it, javaSearchScope) }
override fun knownClassNamesInPackage(packageFqName: FqName): Set<String>? = javaFacade.knownClassNamesInPackage(packageFqName)
}
}
@@ -201,11 +201,16 @@ class BinaryJavaClass(
override fun visitAnnotation(desc: String, visible: Boolean) =
BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
override fun findInnerClass(name: Name): JavaClass? {
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
fun findInnerClass(name: Name, classFileContent: ByteArray?): JavaClass? {
val access = ownInnerClassNameToAccess[name] ?: return null
return virtualFile.parent.findChild("${virtualFile.nameWithoutExtension}$$name.class")?.let {
BinaryJavaClass(it, fqName.child(name), context.copyForMember(), signatureParser, access, this)
BinaryJavaClass(
it, fqName.child(name), context.copyForMember(), signatureParser, access, this,
classFileContent
)
}
}
}
@@ -28,14 +28,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -53,7 +56,9 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
if (file.name == PsiJavaModule.MODULE_INFO_CLS_FILE) return null
@@ -62,7 +67,7 @@ class KotlinBinaryClassCache : Disposable {
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
@@ -27,14 +27,17 @@ class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
internal var result: KotlinClassFinder.Result? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
fun cache(
file: VirtualFile,
result: KotlinClassFinder.Result?
): KotlinClassFinder.Result? {
virtualFile = file
virtualFileKotlinClass = aClass
this.result = result
modificationStamp = file.modificationStamp
return aClass
return result
}
}
@@ -52,14 +55,16 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
return requestCache.result
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
@@ -27,12 +27,12 @@ import org.jetbrains.kotlin.utils.sure
abstract class VirtualFileFinder : KotlinClassFinder {
abstract fun findVirtualFileWithHeader(classId: ClassId): VirtualFile?
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? {
val file = findVirtualFileWithHeader(classId) ?: return null
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
}
override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? {
override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? {
var file = (javaClass as? VirtualFileBoundJavaClass)?.virtualFile ?: return null
if (javaClass.outerClass != null) {
@@ -41,7 +41,7 @@ abstract class VirtualFileFinder : KotlinClassFinder {
file = file.parent!!.findChild(classFileName(javaClass) + ".class").sure { "Virtual file not found for $javaClass" }
}
return KotlinBinaryClassCache.getKotlinBinaryClass(file)
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
}
private fun classFileName(jClass: JavaClass): String {
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.util.PerformanceCounter
@@ -56,17 +57,19 @@ class VirtualFileKotlinClass private constructor(
private val perfCounter = PerformanceCounter.create("Binary class from Kotlin file")
@Deprecated("Use KotlinBinaryClassCache")
fun create(file: VirtualFile, fileContent: ByteArray?): VirtualFileKotlinClass? {
fun create(file: VirtualFile, fileContent: ByteArray?): KotlinClassFinder.Result? {
return perfCounter.time {
assert(file.fileType == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
try {
val byteContent = fileContent ?: file.contentsToByteArray(false)
if (!byteContent.isEmpty()) {
return@time FileBasedKotlinClass.create(byteContent) {
name, classVersion, header, innerClasses ->
val kotlinJvmBinaryClass = FileBasedKotlinClass.create(byteContent) { name, classVersion, header, innerClasses ->
VirtualFileKotlinClass(file, name, classVersion, header, innerClasses)
}
return@time kotlinJvmBinaryClass?.let(::KotlinClass)
?: KotlinClassFinder.Result.ClassFileContent(byteContent)
}
}
catch (e: FileNotFoundException) {
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.resolve.jvm
import com.intellij.psi.impl.file.impl.JavaFileManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
interface KotlinCliJavaFileManager : JavaFileManager {
fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass?
fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass?
fun knownClassNamesInPackage(packageFqName: FqName): Set<String>?
}
@@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.KtLightClassMarker;
import org.jetbrains.kotlin.idea.KotlinLanguage;
import org.jetbrains.kotlin.load.java.JavaClassFinder;
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl;
import org.jetbrains.kotlin.load.java.structure.JavaClass;
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl;
@@ -104,9 +105,10 @@ public class KotlinJavaPsiFacade {
return emptyModifierList;
}
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly
ClassId classId = request.getClassId();
String qualifiedName = classId.asSingleFqName().asString();
if (shouldUseSlowResolve()) {
@@ -119,7 +121,7 @@ public class KotlinJavaPsiFacade {
for (KotlinPsiElementFinderWrapper finder : finders()) {
if (finder instanceof CliFinder) {
JavaClass aClass = ((CliFinder) finder).findClass(classId, scope);
JavaClass aClass = ((CliFinder) finder).findClass(request, scope);
if (aClass != null) return aClass;
}
else {
@@ -383,8 +385,8 @@ public class KotlinJavaPsiFacade {
return javaFileManager.findClass(qualifiedName, scope);
}
public JavaClass findClass(@NotNull ClassId classId, @NotNull GlobalSearchScope scope) {
return javaFileManager.findClass(classId, scope);
public JavaClass findClass(@NotNull JavaClassFinder.Request request, @NotNull GlobalSearchScope scope) {
return javaFileManager.findClass(request, scope);
}
@Nullable
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.javac.components
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.load.java.JavaClassFinder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
@@ -32,10 +32,12 @@ class JavacBasedClassFinder : AbstractJavaClassFinder() {
super.initialize(trace, codeAnalyzer)
}
override fun findClass(classId: ClassId) = javac.findClass(classId, javaSearchScope)
override fun findClass(request: JavaClassFinder.Request) =
// TODO: reuse previouslyFoundClassFileContent if it's possible in javac
javac.findClass(request.classId, javaSearchScope)
override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope)
override fun knownClassNamesInPackage(packageFqName: FqName) = javac.knownClassNamesInPackage(packageFqName)
}
}
@@ -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?
@@ -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)
}
@@ -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()
}
}
@@ -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 =
@@ -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)
}
@@ -60,7 +60,7 @@ object IDEKotlinBinaryClassCache {
return null
}
val kotlinBinaryClass = KotlinBinaryClassCache.getKotlinBinaryClass(file, fileContent)
val kotlinBinaryClass = KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file, fileContent)?.toKotlinJvmBinaryClass()
val isKotlinBinaryClass = kotlinBinaryClass != null
if (file is VirtualFileWithId) {
@@ -31,12 +31,16 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.classId
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import java.io.InputStream
@@ -109,16 +113,16 @@ class DirectoryBasedClassFinder(
val packageDirectory: VirtualFile,
val directoryPackageFqName: FqName
) : KotlinClassFinder {
override fun findKotlinClass(javaClass: JavaClass) = findKotlinClass(javaClass.classId!!)
override fun findKotlinClassOrContent(javaClass: JavaClass) = findKotlinClassOrContent(javaClass.classId!!)
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? {
if (classId.packageFqName != directoryPackageFqName) {
return null
}
val targetName = classId.relativeClassName.pathSegments().joinToString("$", postfix = ".class")
val virtualFile = packageDirectory.findChild(targetName)
if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile)) {
return IDEKotlinBinaryClassCache.getKotlinBinaryClass(virtualFile)
return IDEKotlinBinaryClassCache.getKotlinBinaryClass(virtualFile)?.let(::KotlinClass)
}
return null
}