Refactor KotlinJvmBinaryClass, VirtualFileKotlinClass, etc.

VirtualFileKotlinClass now reads its header and name on creation. This is not
lazy enough and may be slower in some circumstances, but has the following
advantage: if anything is wrong in the header, a VirtualFileKotlinClass
instance will not be created at all, making it nearly impossible for the client
code to operate on invalid data causing all kinds of exceptions
This commit is contained in:
Alexander Udalov
2014-03-12 20:41:49 +04:00
parent 9bf0d014d5
commit 307f52895a
13 changed files with 78 additions and 104 deletions
@@ -29,8 +29,6 @@ import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.resolve.java.JavaResolverPsiUtils;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -113,9 +111,8 @@ public class JetFromJavaDescriptorHelper {
VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass);
if (virtualFile != null) {
KotlinJvmBinaryClass kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile);
KotlinClassHeader header = kotlinClass.getClassHeader();
if (header != null) {
return header.getAnnotationData();
if (kotlinClass != null) {
return kotlinClass.getClassHeader().getAnnotationData();
}
}
return null;
@@ -35,10 +35,9 @@ public fun buildDecompiledText(
resolver: ResolverForDecompiler = DeserializerForDecompiler(classFile)
): DecompiledText {
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
val classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars()
val classFileHeader = kotlinClass.getClassHeader()
assert(classFileHeader != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
val kind = classFileHeader!!.kind
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
val classFqName = kotlinClass!!.getClassName().getFqNameForClassNameWithoutDollars()
val kind = kotlinClass.getClassHeader().kind
val packageFqName = classFqName.parent()
return if (kind == KotlinClassHeader.Kind.PACKAGE_FACADE) {
@@ -30,7 +30,7 @@ public fun isKotlinCompiledFile(file: VirtualFile): Boolean {
if (isKotlinCompiledFileWithIncompatibleAbiVersion(file)) {
return false
}
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file).getClassHeader()
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader()
return header != null && header.syntheticClassKind != KotlinSyntheticClass.Kind.TRAIT_IMPL
}
@@ -38,7 +38,7 @@ public fun isKotlinCompiledFileWithIncompatibleAbiVersion(file: VirtualFile): Bo
if (file.getExtension() != StdFileTypes.CLASS.getDefaultExtension()) {
return false
}
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file).getClassHeader()
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader()
return header?.kind == KotlinClassHeader.Kind.INCOMPATIBLE_ABI_VERSION
}
@@ -49,6 +49,6 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
if (ClassFileViewProvider.isInnerClass(file)) {
return true
}
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file).getClassHeader()
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader()
return header?.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS
}
@@ -46,7 +46,8 @@ import org.jetbrains.jet.lang.resolve.kotlin.ConstantDescriptorDeserializer
public fun DeserializerForDecompiler(classFile: VirtualFile): DeserializerForDecompiler {
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
val classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars()
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
val classFqName = kotlinClass!!.getClassName().getFqNameForClassNameWithoutDollars()
val packageFqName = classFqName.parent()
return DeserializerForDecompiler(classFile.getParent()!!, packageFqName)
}
@@ -174,7 +175,7 @@ public class DeserializerForDecompiler(val packageDirectory: VirtualFile, val di
}
private fun deserializeBinaryClass(kotlinClass: KotlinJvmBinaryClass): ClassDescriptor {
val data = kotlinClass.getClassHeader()?.annotationData
val data = kotlinClass.getClassHeader().annotationData
if (data == null) {
LOG.error("Annotation data missing for ${kotlinClass.getClassName()}")
}
@@ -76,8 +76,7 @@ public final class KotlinClassFileIndex extends ScalarIndexExtension<FqName> {
public Map<FqName, Void> map(FileContent inputData) {
try {
KotlinJvmBinaryClass kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(inputData.getFile());
KotlinClassHeader header = kotlinClass.getClassHeader();
if (header != null && header.getKind() != KotlinClassHeader.Kind.INCOMPATIBLE_ABI_VERSION) {
if (kotlinClass != null && kotlinClass.getClassHeader().getKind() != KotlinClassHeader.Kind.INCOMPATIBLE_ABI_VERSION) {
return Collections.singletonMap(kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null);
}
}
@@ -79,7 +79,7 @@ public class InternalCompiledClassesTest : JetLightCodeInsightFixtureTestCase()
}
private fun isSyntheticClassOfKind(kind: KotlinSyntheticClass.Kind) : VirtualFile.() -> Boolean = {
val header = KotlinBinaryClassCache.getKotlinBinaryClass(this).getClassHeader()
val header = KotlinBinaryClassCache.getKotlinBinaryClass(this)?.getClassHeader()
header?.syntheticClassKind == kind
}