ReadDataFromAnnotationVisitor doesn't depend on ASM anymore

This commit is contained in:
Alexander Udalov
2013-09-26 16:21:12 +04:00
parent 8b63665b20
commit 3087c6f584
5 changed files with 116 additions and 64 deletions
@@ -87,17 +87,23 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
} }
@Nullable @Nullable
private static org.jetbrains.asm4.AnnotationVisitor convertAnnotationVisitor( private static org.jetbrains.asm4.AnnotationVisitor convertAnnotationVisitor(@NotNull AnnotationVisitor visitor, @NotNull String desc) {
@NotNull AnnotationVisitor visitor, AnnotationArgumentVisitor v = visitor.visitAnnotation(classNameFromAsmDesc(desc));
@NotNull String desc return v == null ? null : convertAnnotationVisitor(v);
) { }
final AnnotationArgumentVisitor v = visitor.visitAnnotation(classNameFromAsmDesc(desc));
if (v == null) return null;
@NotNull
private static org.jetbrains.asm4.AnnotationVisitor convertAnnotationVisitor(@NotNull final AnnotationArgumentVisitor v) {
return new org.jetbrains.asm4.AnnotationVisitor(ASM4) { return new org.jetbrains.asm4.AnnotationVisitor(ASM4) {
@Override @Override
public void visit(String name, Object value) { public void visit(String name, Object value) {
v.visit(Name.identifier(name), value); v.visit(name == null ? null : Name.identifier(name), value);
}
@Override
public org.jetbrains.asm4.AnnotationVisitor visitArray(String name) {
AnnotationArgumentVisitor av = v.visitArray(Name.guess(name));
return av == null ? null : convertAnnotationVisitor(av);
} }
@Override @Override
@@ -147,7 +153,7 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
@Override @Override
public void visitEnd() { public void visitEnd() {
super.visitEnd(); v.visitEnd();
} }
}; };
} }
@@ -157,9 +157,11 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
return new KotlinJvmBinaryClass.AnnotationArgumentVisitor() { return new KotlinJvmBinaryClass.AnnotationArgumentVisitor() {
@Override @Override
public void visit(@NotNull Name name, @Nullable Object value) { public void visit(@Nullable Name name, @Nullable Object value) {
CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null); if (name != null) {
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name)); CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
}
} }
@Override @Override
@@ -167,6 +169,13 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
setArgumentValueByName(name, enumEntryValue(enumClassName, enumEntryName)); setArgumentValueByName(name, enumEntryValue(enumClassName, enumEntryName));
} }
@Nullable
@Override
public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitArray(@NotNull Name name) {
// TODO: support arrays
return null;
}
@NotNull @NotNull
private CompileTimeConstant<?> enumEntryValue(@NotNull JvmClassName enumClassName, @NotNull Name name) { private CompileTimeConstant<?> enumEntryValue(@NotNull JvmClassName enumClassName, @NotNull Name name) {
ClassDescriptor enumClass = javaClassResolver.resolveClass(enumClassName.getFqName(), IGNORE_KOTLIN_SOURCES); ClassDescriptor enumClass = javaClassResolver.resolveClass(enumClassName.getFqName(), IGNORE_KOTLIN_SOURCES);
@@ -51,11 +51,14 @@ public interface KotlinJvmBinaryClass {
} }
interface AnnotationArgumentVisitor { interface AnnotationArgumentVisitor {
// TODO: arrays, annotations, java.lang.Class // TODO: annotations, java.lang.Class
void visit(@NotNull Name name, @Nullable Object value); void visit(@Nullable Name name, @Nullable Object value);
void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName); void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName);
@Nullable
AnnotationArgumentVisitor visitArray(@NotNull Name name);
void visitEnd(); void visitEnd();
} }
} }
@@ -18,25 +18,14 @@ package org.jetbrains.jet.lang.resolve.kotlin.header;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import java.io.IOException;
import static org.jetbrains.asm4.ClassReader.*;
public abstract class KotlinClassFileHeader { public abstract class KotlinClassFileHeader {
@Nullable @Nullable
public static KotlinClassFileHeader readKotlinHeaderFromClassFile(@NotNull KotlinJvmBinaryClass kotlinClass) { public static KotlinClassFileHeader readKotlinHeaderFromClassFile(@NotNull KotlinJvmBinaryClass kotlinClass) {
try { ReadDataFromAnnotationVisitor visitor = new ReadDataFromAnnotationVisitor();
ClassReader reader = new ClassReader(kotlinClass.getFile().contentsToByteArray()); kotlinClass.loadClassAnnotations(visitor);
ReadDataFromAnnotationVisitor visitor = new ReadDataFromAnnotationVisitor(); return visitor.createHeader(kotlinClass);
reader.accept(visitor, SKIP_CODE | SKIP_FRAMES | SKIP_DEBUG);
return visitor.createHeader(kotlinClass);
}
catch (IOException e) {
throw new RuntimeException(e);
}
} }
private final int version; private final int version;
@@ -19,20 +19,20 @@ package org.jetbrains.jet.lang.resolve.kotlin.header;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil; import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible; import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationArgumentVisitor;
import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationVisitor;
/* package */ class ReadDataFromAnnotationVisitor extends ClassVisitor { /* package */ class ReadDataFromAnnotationVisitor implements AnnotationVisitor {
private static final Logger LOG = Logger.getInstance(ReadDataFromAnnotationVisitor.class); private static final Logger LOG = Logger.getInstance(ReadDataFromAnnotationVisitor.class);
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@@ -51,9 +51,9 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
} }
@Nullable @Nullable
private static HeaderType byDescriptor(@NotNull String desc) { private static HeaderType byClassName(@NotNull JvmClassName className) {
for (HeaderType headerType : HeaderType.values()) { for (HeaderType headerType : HeaderType.values()) {
if (desc.equals(headerType.annotation.getDescriptor())) { if (className.equals(headerType.annotation)) {
return headerType; return headerType;
} }
} }
@@ -67,10 +67,6 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
@Nullable @Nullable
private HeaderType foundType = null; private HeaderType foundType = null;
public ReadDataFromAnnotationVisitor() {
super(Opcodes.ASM4);
}
@Nullable @Nullable
public KotlinClassFileHeader createHeader(@NotNull KotlinJvmBinaryClass kotlinClass) { public KotlinClassFileHeader createHeader(@NotNull KotlinJvmBinaryClass kotlinClass) {
if (foundType == null) { if (foundType == null) {
@@ -102,9 +98,10 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
return new SerializedDataHeader(version, annotationData, kind); return new SerializedDataHeader(version, annotationData, kind);
} }
@Nullable
@Override @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { public AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName annotationClassName) {
HeaderType newType = HeaderType.byDescriptor(desc); HeaderType newType = HeaderType.byClassName(annotationClassName);
if (newType == null) return null; if (newType == null) return null;
if (foundType != null) { if (foundType != null) {
@@ -115,41 +112,51 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
foundType = newType; foundType = newType;
if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) { if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) {
return kotlinClassOrPackageVisitor(desc); return kotlinClassOrPackageVisitor(annotationClassName);
} }
else if (newType == HeaderType.PACKAGE_FRAGMENT) { else if (newType == HeaderType.PACKAGE_FRAGMENT) {
return kotlinPackageFragmentVisitor(desc); return kotlinPackageFragmentVisitor(annotationClassName);
} }
return null; return null;
} }
@Override
public void visitEnd() {
}
@NotNull @NotNull
private AnnotationVisitor kotlinClassOrPackageVisitor(final String desc) { private AnnotationArgumentVisitor kotlinClassOrPackageVisitor(@NotNull final JvmClassName annotationClassName) {
return new AnnotationVisitor(Opcodes.ASM4) { return new AnnotationArgumentVisitor() {
@Override @Override
public void visit(String name, Object value) { public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, desc); visitIntValueForSupportedAnnotation(name, value, annotationClassName);
} }
@Override @Override
public AnnotationVisitor visitArray(String name) { public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
if (name.equals(JvmAnnotationNames.DATA_FIELD_NAME)) { unexpectedArgument(name, annotationClassName);
}
@Override
@Nullable
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
return stringArrayVisitor(); return stringArrayVisitor();
} }
else if (isAbiVersionCompatible(version)) { else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + desc); throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + annotationClassName);
} }
return super.visitArray(name); return null;
} }
@NotNull @NotNull
private AnnotationVisitor stringArrayVisitor() { private AnnotationArgumentVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1); final List<String> strings = new ArrayList<String>(1);
return new AnnotationVisitor(Opcodes.ASM4) { return new AnnotationArgumentVisitor() {
@Override @Override
public void visit(String name, Object value) { public void visit(@Nullable Name name, @Nullable Object value) {
if (!(value instanceof String)) { if (!(value instanceof String)) {
throw new IllegalStateException("Unexpected argument value: " + value); throw new IllegalStateException("Unexpected argument value: " + value);
} }
@@ -157,31 +164,69 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
strings.add((String) value); strings.add((String) value);
} }
@Override
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
unexpectedArgument(name, annotationClassName);
}
@Nullable
@Override
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, annotationClassName);
}
@Override @Override
public void visitEnd() { public void visitEnd() {
annotationData = strings.toArray(new String[strings.size()]); annotationData = strings.toArray(new String[strings.size()]);
} }
}; };
} }
};
}
@NotNull
private AnnotationVisitor kotlinPackageFragmentVisitor(final String desc) {
return new AnnotationVisitor(Opcodes.ASM4) {
@Override @Override
public void visit(String name, Object value) { public void visitEnd() {
visitIntValueForSupportedAnnotation(name, value, desc);
} }
}; };
} }
private void visitIntValueForSupportedAnnotation(@NotNull String name, @NotNull Object value, @NotNull String desc) { @NotNull
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) { private AnnotationArgumentVisitor kotlinPackageFragmentVisitor(@NotNull final JvmClassName annotationClassName) {
version = (Integer) value; return new AnnotationArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, annotationClassName);
}
@Override
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
unexpectedArgument(name, annotationClassName);
}
@Nullable
@Override
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, annotationClassName);
}
@Override
public void visitEnd() {
}
};
}
private void visitIntValueForSupportedAnnotation(@Nullable Name name, @Nullable Object value, @NotNull JvmClassName className) {
if (name != null && name.asString().equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
version = value == null ? AbiVersionUtil.INVALID_VERSION : (Integer) value;
} }
else if (isAbiVersionCompatible(version)) { else {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc); unexpectedArgument(name, className);
} }
} }
@Nullable
private AnnotationArgumentVisitor unexpectedArgument(@Nullable Name name, @NotNull JvmClassName annotationClassName) {
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + annotationClassName);
}
return null;
}
} }