ReadDataFromAnnotationVisitor doesn't depend on ASM anymore
This commit is contained in:
+14
-8
@@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -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);
|
||||||
|
|||||||
+5
-2
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-14
@@ -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;
|
||||||
|
|||||||
+82
-37
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user