KotlinJvmBinaryClass now has a getClassHeader() method

This commit is contained in:
Andrey Breslav
2014-01-07 13:21:15 +04:00
parent 7fc9772930
commit b3f4527bb8
10 changed files with 65 additions and 30 deletions
@@ -19,8 +19,8 @@ package org.jetbrains.jet.cli.jvm.compiler;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.kotlin.*;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClassFinder;
import org.jetbrains.jet.lang.resolve.name.FqName;
public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implements VirtualFileFinder {
@@ -70,7 +70,7 @@ public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implement
return null;
}
//NOTE: currently we use VirtualFileFinder to find Kotlin binaries only
if (KotlinClassHeader.read(createKotlinClass(vFile)) != null) {
if (createKotlinClass(vFile).getClassHeader() != null) {
return vFile;
}
}
@@ -16,7 +16,9 @@
package org.jetbrains.jet.lang.resolve.kotlin;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import jet.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.ClassReader;
@@ -24,7 +26,11 @@ import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.FieldVisitor;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.storage.NotNullLazyValue;
import org.jetbrains.jet.storage.NullableLazyValue;
import org.jetbrains.jet.storage.StorageManager;
import org.jetbrains.jet.utils.ExceptionUtils;
import java.io.IOException;
@@ -34,10 +40,27 @@ import static org.jetbrains.asm4.Opcodes.ASM4;
public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
private final VirtualFile file;
private JvmClassName className;
private final NotNullLazyValue<JvmClassName> className;
private final NullableLazyValue<KotlinClassHeader> classHeader;
public VirtualFileKotlinClass(@NotNull VirtualFile file) {
public VirtualFileKotlinClass(@NotNull StorageManager storageManager, @NotNull VirtualFile file) {
this.file = file;
this.className = storageManager.createLazyValue(
new Function0<JvmClassName>() {
@Override
public JvmClassName invoke() {
return computeClassName();
}
}
);
this.classHeader = storageManager.createNullableLazyValue(
new Function0<KotlinClassHeader>() {
@Override
public KotlinClassHeader invoke() {
return KotlinClassHeader.read(VirtualFileKotlinClass.this);
}
}
);
}
@NotNull
@@ -45,24 +68,32 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
return file;
}
@NotNull
private JvmClassName computeClassName() {
final Ref<JvmClassName> classNameRef = Ref.create();
try {
new ClassReader(file.contentsToByteArray()).accept(new ClassVisitor(ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classNameRef.set(JvmClassName.byInternalName(name));
}
}, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
return classNameRef.get();
}
@NotNull
@Override
public JvmClassName getClassName() {
if (className == null) {
try {
new ClassReader(file.contentsToByteArray()).accept(new ClassVisitor(ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className = JvmClassName.byInternalName(name);
}
}, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
}
return className.invoke();
}
return className;
@Override
public KotlinClassHeader getClassHeader() {
return classHeader.invoke();
}
@Override
@@ -21,6 +21,7 @@ import com.intellij.util.containers.SLRUCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.storage.LockBasedStorageManager;
public abstract class VirtualFileKotlinClassFinder implements VirtualFileFinder {
@@ -29,7 +30,8 @@ public abstract class VirtualFileKotlinClassFinder implements VirtualFileFinder
@NotNull
@Override
public KotlinJvmBinaryClass createValue(VirtualFile virtualFile) {
return new VirtualFileKotlinClass(virtualFile);
// Operations under this lock are not supposed to involve other locks
return new VirtualFileKotlinClass(new LockBasedStorageManager(), virtualFile);
}
};
@@ -113,7 +113,7 @@ public final class DeserializedDescriptorResolver {
@Nullable
private String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @NotNull SerializedDataHeader.Kind expectedKind) {
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
KotlinClassHeader header = kotlinClass.getClassHeader();
if (header instanceof SerializedDataHeader) {
SerializedDataHeader serializedDataHeader = (SerializedDataHeader) header;
if (serializedDataHeader.getKind() != expectedKind) return null;
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.kotlin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.name.Name;
public interface KotlinJvmBinaryClass {
@@ -29,6 +30,9 @@ public interface KotlinJvmBinaryClass {
void loadMemberAnnotations(@NotNull MemberVisitor visitor);
@Nullable
KotlinClassHeader getClassHeader();
interface MemberVisitor {
// TODO: abstract signatures for methods and fields instead of ASM 'desc' strings?
@@ -31,7 +31,6 @@ import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.resolve.java.JavaResolverPsiUtils;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -120,7 +119,7 @@ public class JetFromJavaDescriptorHelper {
VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass);
if (virtualFile != null) {
KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(psiClass.getProject()).createKotlinClass(virtualFile);
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
KotlinClassHeader header = kotlinClass.getClassHeader();
if (header instanceof SerializedDataHeader) {
return ((SerializedDataHeader) header).getAnnotationData();
}
@@ -71,7 +71,7 @@ public final class DecompiledDataFactory {
KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(project).createKotlinClass(classFile);
this.classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars();
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
KotlinClassHeader header = kotlinClass.getClassHeader();
assert header instanceof SerializedDataHeader : "Decompiled data factory shouldn't be called on an unsupported file: " + classFile;
this.classFileHeader = (SerializedDataHeader) header;
}
@@ -22,7 +22,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
public final class DecompiledUtils {
@@ -33,7 +32,7 @@ public final class DecompiledUtils {
}
//TODO: check index
KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(project).createKotlinClass(file);
return KotlinClassHeader.read(kotlinClass) instanceof SerializedDataHeader;
return kotlinClass.getClassHeader() instanceof SerializedDataHeader;
}
private DecompiledUtils() {
@@ -27,8 +27,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.PackageFragmentClassHeader;
import org.jetbrains.jet.storage.LockBasedStorageManager;
/**
* This class is needed to build an empty PSI stub for compiled package fragment classes. This results in these classes not showing up
@@ -46,8 +46,8 @@ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFac
public boolean canBeProcessed(VirtualFile file, byte[] bytes) {
if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") &&
StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) {
KotlinJvmBinaryClass kotlinClass = new VirtualFileKotlinClass(file);
return KotlinClassHeader.read(kotlinClass) instanceof PackageFragmentClassHeader;
KotlinJvmBinaryClass kotlinClass = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file);
return kotlinClass.getClassHeader() instanceof PackageFragmentClassHeader;
}
return false;
}
@@ -78,7 +78,7 @@ public final class KotlinClassFileIndex extends ScalarIndexExtension<FqName> {
try {
KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(inputData.getProject())
.createKotlinClass(inputData.getFile());
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
KotlinClassHeader header = kotlinClass.getClassHeader();
if (header != null && !(header instanceof IncompatibleAnnotationHeader)) {
return Collections.singletonMap(kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null);
}