name.remal.asm.AsmUtils Maven / Gradle / Ivy
package name.remal.asm;
import static name.remal.ArrayUtils.arrayToString;
import static name.remal.annotation.AnnotationUtils.getAttributes;
import static org.objectweb.asm.Type.getDescriptor;
import static org.objectweb.asm.Type.getType;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
public class AsmUtils {
public static final int ASM_API;
static {
try {
ClassWriter classWriter = new ClassWriter(0);
Field apiField = ClassVisitor.class.getDeclaredField("api");
apiField.setAccessible(true);
ASM_API = apiField.getInt(classWriter);
} catch (@NotNull NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@NotNull
@SuppressFBWarnings("CLI_CONSTANT_LIST_INDEX")
public static Object fromJavaToBytecodeAnnotationValue(@NotNull Object value) {
if (value instanceof Byte) {
return value;
} else if (value instanceof Boolean) {
return value;
} else if (value instanceof Character) {
return value;
} else if (value instanceof Short) {
return value;
} else if (value instanceof Integer) {
return value;
} else if (value instanceof Long) {
return value;
} else if (value instanceof Float) {
return value;
} else if (value instanceof Double) {
return value;
} else if (value instanceof String) {
return value;
} else if (value instanceof Type) {
return value;
} else if (value instanceof Class) {
return getType((Class) value);
} else if (value instanceof String[]) {
String[] typedValue = (String[]) value;
if (2 != typedValue.length || null == typedValue[0] || null == typedValue[1]) throw new IllegalArgumentException("Unsupported enum value: " + arrayToString((Object[]) typedValue));
return value;
} else if (value instanceof Enum) {
Enum typedValue = (Enum) value;
return new String[]{getDescriptor(typedValue.getDeclaringClass()), typedValue.name()};
} else if (value instanceof AnnotationNode) {
return value;
} else if (value instanceof Annotation) {
Annotation typedValue = (Annotation) value;
AnnotationNode annotationNode = new AnnotationNode(getDescriptor(typedValue.annotationType()));
annotationNode.values = new ArrayList<>();
getAttributes(typedValue).forEach((fieldName, fieldValue) -> {
annotationNode.values.add(fieldName);
annotationNode.values.add(fromJavaToBytecodeAnnotationValue(fieldValue));
});
return annotationNode;
} else if (value instanceof List) {
List typedValue = (List) value;
List