Avoid repeated reading of file contents from disk while building stubs
This commit is contained in:
+6
-4
@@ -143,8 +143,9 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadClassAnnotations(@NotNull final AnnotationVisitor annotationVisitor) {
|
||||
new ClassReader(getFileContents()).accept(new ClassVisitor(ASM5) {
|
||||
public void loadClassAnnotations(@NotNull final AnnotationVisitor annotationVisitor, @Nullable byte[] cachedContents) {
|
||||
byte[] fileContents = cachedContents != null ? cachedContents : getFileContents();
|
||||
new ClassReader(fileContents).accept(new ClassVisitor(ASM5) {
|
||||
@Override
|
||||
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitAnnotation(@NotNull String desc, boolean visible) {
|
||||
return convertAnnotationVisitor(annotationVisitor, desc, innerClasses);
|
||||
@@ -215,8 +216,9 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMembers(@NotNull final MemberVisitor memberVisitor) {
|
||||
new ClassReader(getFileContents()).accept(new ClassVisitor(ASM5) {
|
||||
public void visitMembers(@NotNull final MemberVisitor memberVisitor, @Nullable byte[] cachedContents) {
|
||||
byte[] fileContents = cachedContents != null ? cachedContents : getFileContents();
|
||||
new ClassReader(fileContents).accept(new ClassVisitor(ASM5) {
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, @NotNull String name, @NotNull String desc, String signature, Object value) {
|
||||
final AnnotationVisitor v = memberVisitor.visitField(Name.identifier(name), desc, value);
|
||||
|
||||
+4
-2
@@ -67,6 +67,8 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
private fun ProtoContainer.Class.toBinaryClass(): KotlinJvmBinaryClass? =
|
||||
(source as? KotlinJvmBinarySourceElement)?.binaryClass
|
||||
|
||||
protected open fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? = null
|
||||
|
||||
override fun loadClassAnnotations(container: ProtoContainer.Class): List<A> {
|
||||
val kotlinClass = container.toBinaryClass() ?: error("Class for loading annotations is not found: ${container.debugFqName()}")
|
||||
|
||||
@@ -79,7 +81,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
|
||||
override fun visitEnd() {
|
||||
}
|
||||
})
|
||||
}, getCachedFileContent(kotlinClass))
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -294,7 +296,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}, getCachedFileContent(kotlinClass))
|
||||
|
||||
return Storage(memberAnnotations, propertyConstants)
|
||||
}
|
||||
|
||||
+2
-2
@@ -29,9 +29,9 @@ interface KotlinJvmBinaryClass {
|
||||
*/
|
||||
val location: String
|
||||
|
||||
fun loadClassAnnotations(visitor: AnnotationVisitor)
|
||||
fun loadClassAnnotations(visitor: AnnotationVisitor, cachedContents: ByteArray?)
|
||||
|
||||
fun visitMembers(visitor: MemberVisitor)
|
||||
fun visitMembers(visitor: MemberVisitor, cachedContents: ByteArray?)
|
||||
|
||||
val classHeader: KotlinClassHeader
|
||||
|
||||
|
||||
+2
-3
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin.reflect
|
||||
|
||||
import com.sun.xml.internal.ws.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.desc
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.isEnumClassOrSpecializedEnumEntryClass
|
||||
@@ -61,11 +60,11 @@ class ReflectKotlinClass private constructor(
|
||||
override val classId: ClassId
|
||||
get() = klass.classId
|
||||
|
||||
override fun loadClassAnnotations(visitor: KotlinJvmBinaryClass.AnnotationVisitor) {
|
||||
override fun loadClassAnnotations(visitor: KotlinJvmBinaryClass.AnnotationVisitor, cachedContents: ByteArray?) {
|
||||
ReflectClassStructure.loadClassAnnotations(klass, visitor)
|
||||
}
|
||||
|
||||
override fun visitMembers(visitor: KotlinJvmBinaryClass.MemberVisitor) {
|
||||
override fun visitMembers(visitor: KotlinJvmBinaryClass.MemberVisitor, cachedContents: ByteArray?) {
|
||||
ReflectClassStructure.visitMembers(klass, visitor)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() {
|
||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||
val virtualFile = content.file
|
||||
assert(virtualFile.fileType == KotlinBuiltInFileType) { "Unexpected file type ${virtualFile.fileType}" }
|
||||
val file = BuiltInDefinitionFile.read(virtualFile) ?: return null
|
||||
val file = BuiltInDefinitionFile.read(content.content, virtualFile) ?: return null
|
||||
|
||||
when (file) {
|
||||
is BuiltInDefinitionFile.Incompatible -> {
|
||||
|
||||
+17
-11
@@ -26,10 +26,7 @@ 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.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.*
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -51,11 +48,11 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
return null
|
||||
}
|
||||
|
||||
return doBuildFileStub(file)
|
||||
return doBuildFileStub(file, content.content)
|
||||
}
|
||||
|
||||
fun doBuildFileStub(file: VirtualFile): PsiFileStub<KtFile>? {
|
||||
val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClass(file) ?: error("Can't find binary class for Kotlin file: $file")
|
||||
fun doBuildFileStub(file: VirtualFile, fileContent: ByteArray): PsiFileStub<KtFile>? {
|
||||
val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClass(file, fileContent) ?: error("Can't find binary class for Kotlin file: $file")
|
||||
val header = kotlinClass.classHeader
|
||||
val classId = kotlinClass.classId
|
||||
val packageFqName = classId.packageFqName
|
||||
@@ -63,7 +60,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
return createIncompatibleAbiVersionFileStub()
|
||||
}
|
||||
|
||||
val components = createStubBuilderComponents(file, packageFqName)
|
||||
val components = createStubBuilderComponents(file, packageFqName, fileContent)
|
||||
if (header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS) {
|
||||
val partFiles = findMultifileClassParts(file, classId, header)
|
||||
return createMultifileClassStub(header, partFiles, classId.asSingleFqName(), components)
|
||||
@@ -95,10 +92,10 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName): ClsStubBuilderComponents {
|
||||
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, fileContent: ByteArray): ClsStubBuilderComponents {
|
||||
val classFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
|
||||
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
|
||||
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder)
|
||||
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, file, fileContent)
|
||||
return ClsStubBuilderComponents(classDataFinder, annotationLoader, file)
|
||||
}
|
||||
|
||||
@@ -108,9 +105,18 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
}
|
||||
|
||||
class AnnotationLoaderForClassFileStubBuilder(
|
||||
kotlinClassFinder: KotlinClassFinder
|
||||
kotlinClassFinder: KotlinClassFinder,
|
||||
private val cachedFile: VirtualFile,
|
||||
private val cachedFileContent: ByteArray
|
||||
) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget>(LockBasedStorageManager.NO_LOCKS, kotlinClassFinder) {
|
||||
|
||||
override fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? {
|
||||
if ((kotlinClass as? VirtualFileKotlinClass)?.file == cachedFile) {
|
||||
return cachedFileContent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId =
|
||||
nameResolver.getClassId(proto.id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user