Do not call findKotlinClass when loading class annotations

The main change is in AbstractBinaryClassAnnotationAndConstantLoader, where we
no longer perform unnecessary IO operations for classes which are already
loaded to memory
This commit is contained in:
Alexander Udalov
2016-04-06 16:18:10 +03:00
parent 7620d66019
commit ad068ed4ac
16 changed files with 68 additions and 70 deletions
@@ -57,7 +57,9 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() {
packageProto.functionList, packageProto.propertyList
)
for (classProto in file.classesToDecompile) {
createClassStub(fileStub, classProto, nameResolver, nameResolver.getClassId(classProto.fqName), context)
createClassStub(
fileStub, classProto, nameResolver, nameResolver.getClassId(classProto.fqName), source = null, context = context
)
}
return fileStub
}
@@ -57,14 +57,13 @@ class DeserializerForClassfileDecompiler(
init {
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
val errorReporter = LoggingErrorReporter(LOG)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader =
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder, errorReporter)
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder)
deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), errorReporter,
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, notFoundClasses
)
}
@@ -26,16 +26,15 @@ import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.*
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.load.kotlin.AbstractBinaryClassAnnotationAndConstantLoader
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
@@ -55,9 +54,9 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
}
fun doBuildFileStub(file: VirtualFile): PsiFileStub<KtFile>? {
val kotlinClassHeaderInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file)!!
val header = kotlinClassHeaderInfo.classHeader
val classId = kotlinClassHeaderInfo.classId
val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClass(file)!!
val header = kotlinClass.classHeader
val classId = kotlinClass.classId
val packageFqName = classId.packageFqName
if (!header.metadataVersion.isCompatible()) {
return createIncompatibleAbiVersionFileStub()
@@ -84,7 +83,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
if (classId.isLocal) return null
val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings)
val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable))
createTopLevelClassStub(classId, classProto, context)
createTopLevelClassStub(classId, classProto, KotlinJvmBinarySourceElement(kotlinClass), context)
}
KotlinClassHeader.Kind.FILE_FACADE -> {
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
@@ -98,7 +97,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName): ClsStubBuilderComponents {
val classFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, LoggingErrorReporter(LOG))
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder)
return ClsStubBuilderComponents(classDataFinder, annotationLoader, file)
}
@@ -108,10 +107,8 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
}
class AnnotationLoaderForClassFileStubBuilder(
kotlinClassFinder: KotlinClassFinder,
errorReporter: ErrorReporter
) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget>(
LockBasedStorageManager.NO_LOCKS, kotlinClassFinder, errorReporter) {
kotlinClassFinder: KotlinClassFinder
) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget>(LockBasedStorageManager.NO_LOCKS, kotlinClassFinder) {
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId =
nameResolver.getClassId(proto.id)
@@ -70,7 +70,7 @@ class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
val classProto = ProtoBuf.Class.parseFrom(content, JsSerializerProtocol.extensionRegistry)
val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable))
val classId = JsMetaFileUtils.getClassId(file)
return createTopLevelClassStub(classId, classProto, context)
return createTopLevelClassStub(classId, classProto, source = null, context = context)
}
}
@@ -37,15 +37,17 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinPlaceHolderStubImpl
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.BinarySource
fun createClassStub(
parent: StubElement<out PsiElement>,
classProto: ProtoBuf.Class,
nameResolver: NameResolver,
classId: ClassId,
source: BinarySource?,
context: ClsStubBuilderContext
) {
ClassClsStubBuilder(parent, classProto, nameResolver, classId, context).build()
ClassClsStubBuilder(parent, classProto, nameResolver, classId, source, context).build()
}
private class ClassClsStubBuilder(
@@ -53,6 +55,7 @@ private class ClassClsStubBuilder(
private val classProto: ProtoBuf.Class,
private val nameResolver: NameResolver,
private val classId: ClassId,
private val source: BinarySource?,
private val outerContext: ClsStubBuilderContext
) {
private val classKind = Flags.CLASS_KIND[classProto.flags]
@@ -73,8 +76,9 @@ private class ClassClsStubBuilder(
private val companionObjectName =
if (classProto.hasCompanionObjectName()) c.nameResolver.getName(classProto.companionObjectName) else null
private val thisAsProtoContainer =
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, outerContext.classKind?.let { Deserialization.classKind(it) })
private val thisAsProtoContainer = ProtoContainer.Class(
classProto, c.nameResolver, c.typeTable, source, outerContext.classKind?.let { Deserialization.classKind(it) }
)
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
@@ -249,7 +253,7 @@ private class ClassClsStubBuilder(
return
}
val (nameResolver, classProto) = classDataWithSource.classData
createClassStub(classBody, classProto, nameResolver, nestedClassId, c)
createClassStub(classBody, classProto, nameResolver, nestedClassId, classDataWithSource.sourceElement as? BinarySource, c)
}
companion object {
@@ -40,11 +40,17 @@ import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.deserialization.descriptors.BinarySource
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
fun createTopLevelClassStub(classId: ClassId, classProto: ProtoBuf.Class, context: ClsStubBuilderContext): KotlinFileStubImpl {
fun createTopLevelClassStub(
classId: ClassId,
classProto: ProtoBuf.Class,
source: BinarySource?,
context: ClsStubBuilderContext
): KotlinFileStubImpl {
val fileStub = createFileStub(classId.packageFqName)
createClassStub(fileStub, classProto, context.nameResolver, classId, context)
createClassStub(fileStub, classProto, context.nameResolver, classId, source, context)
return fileStub
}
@@ -24,10 +24,6 @@ import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
class LoggingErrorReporter(private val log: Logger) : ErrorReporter {
override fun reportLoadingError(message: String, exception: Exception?) {
log.error(message, exception)
}
override fun reportIncompleteHierarchy(descriptor: ClassDescriptor, unresolvedSuperClasses: List<String>) {
// This is absolutely fine for the decompiler
}