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
@@ -157,9 +157,11 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
return new KotlinJvmBinaryClass.AnnotationArgumentVisitor() {
@Override
public void visit(@NotNull Name name, @Nullable Object value) {
CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
public void visit(@Nullable Name name, @Nullable Object value) {
if (name != null) {
CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
}
}
@Override
@@ -167,6 +169,13 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
setArgumentValueByName(name, enumEntryValue(enumClassName, enumEntryName));
}
@Nullable
@Override
public KotlinJvmBinaryClass.AnnotationArgumentVisitor visitArray(@NotNull Name name) {
// TODO: support arrays
return null;
}
@NotNull
private CompileTimeConstant<?> enumEntryValue(@NotNull JvmClassName enumClassName, @NotNull Name name) {
ClassDescriptor enumClass = javaClassResolver.resolveClass(enumClassName.getFqName(), IGNORE_KOTLIN_SOURCES);
@@ -51,11 +51,14 @@ public interface KotlinJvmBinaryClass {
}
interface AnnotationArgumentVisitor {
// TODO: arrays, annotations, java.lang.Class
void visit(@NotNull Name name, @Nullable Object value);
// TODO: annotations, java.lang.Class
void visit(@Nullable Name name, @Nullable Object value);
void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName);
@Nullable
AnnotationArgumentVisitor visitArray(@NotNull Name name);
void visitEnd();
}
}
@@ -18,25 +18,14 @@ package org.jetbrains.jet.lang.resolve.kotlin.header;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import java.io.IOException;
import static org.jetbrains.asm4.ClassReader.*;
public abstract class KotlinClassFileHeader {
@Nullable
public static KotlinClassFileHeader readKotlinHeaderFromClassFile(@NotNull KotlinJvmBinaryClass kotlinClass) {
try {
ClassReader reader = new ClassReader(kotlinClass.getFile().contentsToByteArray());
ReadDataFromAnnotationVisitor visitor = new ReadDataFromAnnotationVisitor();
reader.accept(visitor, SKIP_CODE | SKIP_FRAMES | SKIP_DEBUG);
return visitor.createHeader(kotlinClass);
}
catch (IOException e) {
throw new RuntimeException(e);
}
ReadDataFromAnnotationVisitor visitor = new ReadDataFromAnnotationVisitor();
kotlinClass.loadClassAnnotations(visitor);
return visitor.createHeader(kotlinClass);
}
private final int version;
@@ -19,20 +19,20 @@ package org.jetbrains.jet.lang.resolve.kotlin.header;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
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.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.ArrayList;
import java.util.List;
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);
@SuppressWarnings("deprecation")
@@ -51,9 +51,9 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
}
@Nullable
private static HeaderType byDescriptor(@NotNull String desc) {
private static HeaderType byClassName(@NotNull JvmClassName className) {
for (HeaderType headerType : HeaderType.values()) {
if (desc.equals(headerType.annotation.getDescriptor())) {
if (className.equals(headerType.annotation)) {
return headerType;
}
}
@@ -67,10 +67,6 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
@Nullable
private HeaderType foundType = null;
public ReadDataFromAnnotationVisitor() {
super(Opcodes.ASM4);
}
@Nullable
public KotlinClassFileHeader createHeader(@NotNull KotlinJvmBinaryClass kotlinClass) {
if (foundType == null) {
@@ -102,9 +98,10 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
return new SerializedDataHeader(version, annotationData, kind);
}
@Nullable
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
HeaderType newType = HeaderType.byDescriptor(desc);
public AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName annotationClassName) {
HeaderType newType = HeaderType.byClassName(annotationClassName);
if (newType == null) return null;
if (foundType != null) {
@@ -115,41 +112,51 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
foundType = newType;
if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) {
return kotlinClassOrPackageVisitor(desc);
return kotlinClassOrPackageVisitor(annotationClassName);
}
else if (newType == HeaderType.PACKAGE_FRAGMENT) {
return kotlinPackageFragmentVisitor(desc);
return kotlinPackageFragmentVisitor(annotationClassName);
}
return null;
}
@Override
public void visitEnd() {
}
@NotNull
private AnnotationVisitor kotlinClassOrPackageVisitor(final String desc) {
return new AnnotationVisitor(Opcodes.ASM4) {
private AnnotationArgumentVisitor kotlinClassOrPackageVisitor(@NotNull final JvmClassName annotationClassName) {
return new AnnotationArgumentVisitor() {
@Override
public void visit(String name, Object value) {
visitIntValueForSupportedAnnotation(name, value, desc);
public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, annotationClassName);
}
@Override
public AnnotationVisitor visitArray(String name) {
if (name.equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
unexpectedArgument(name, annotationClassName);
}
@Override
@Nullable
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
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
private AnnotationVisitor stringArrayVisitor() {
private AnnotationArgumentVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1);
return new AnnotationVisitor(Opcodes.ASM4) {
return new AnnotationArgumentVisitor() {
@Override
public void visit(String name, Object value) {
public void visit(@Nullable Name name, @Nullable Object value) {
if (!(value instanceof String)) {
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);
}
@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() {
annotationData = strings.toArray(new String[strings.size()]);
}
};
}
};
}
@NotNull
private AnnotationVisitor kotlinPackageFragmentVisitor(final String desc) {
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
visitIntValueForSupportedAnnotation(name, value, desc);
public void visitEnd() {
}
};
}
private void visitIntValueForSupportedAnnotation(@NotNull String name, @NotNull Object value, @NotNull String desc) {
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
version = (Integer) value;
@NotNull
private AnnotationArgumentVisitor kotlinPackageFragmentVisitor(@NotNull final JvmClassName annotationClassName) {
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)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc);
else {
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;
}
}