LibJF/libjf-config-compiler-plugin/src/main/java/io/gitlab/jfronny/libjf/config/plugin/util/GeneratorAdapter2.java

124 lines
4.5 KiB
Java

package io.gitlab.jfronny.libjf.config.plugin.util;
import io.gitlab.jfronny.libjf.config.plugin.BuildMetadata;
import io.gitlab.jfronny.libjf.config.plugin.asm.value.KnownTypes;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import java.lang.invoke.LambdaMetafactory;
import static org.objectweb.asm.Opcodes.ASM9;
import static org.objectweb.asm.Opcodes.H_INVOKESTATIC;
public class GeneratorAdapter2 extends GeneratorAdapter {
private static final Handle metafactory = new Handle(
H_INVOKESTATIC,
Type.getInternalName(LambdaMetafactory.class),
"metafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
false
);
public GeneratorAdapter2(MethodVisitor methodVisitor, int access, String name, String descriptor) {
super(ASM9, methodVisitor, access, name, descriptor);
}
public void λ(String lambdaMethodName, String lambdaType, Type lambdaDescriptor, Type implDescriptor, String implOwner, String implName) {
invokeDynamic(lambdaMethodName,
lambdaType,
metafactory,
lambdaDescriptor,
new Handle(H_INVOKESTATIC, implOwner, implName, implDescriptor.getInternalName(), false),
implDescriptor);
}
public void λ(String lambdaMethodName, String lambdaType, Type descriptor, String implOwner, String implName) {
λ(lambdaMethodName, lambdaType, descriptor, descriptor, implOwner, implName);
}
public void runnable(String implOwner, String implName) {
λ("run",
"()Ljava/lang/Runnable;",
Type.getType("()V"),
implOwner,
implName);
}
public void supplier(String implOwner, String implName, Type implDescriptor) {
λ("get",
"()Ljava/util/function/Supplier;",
Type.getType("()Ljava/lang/Object;"),
implDescriptor,
implOwner,
implName);
}
public void consumer(String implOwner, String implName, Type implDescriptor) {
λ("accept",
"()Ljava/util/function/Consumer;",
Type.getType("(Ljava/lang/Object;)V"),
implDescriptor,
implOwner,
implName);
}
public void box(Type type) {
Type boxedType;
switch (type.getSort()) {
case Type.VOID:
return;
case Type.CHAR:
boxedType = KnownTypes.CHARACTER_BOX_TYPE;
break;
case Type.BOOLEAN:
boxedType = KnownTypes.BOOLEAN_BOX_TYPE;
break;
case Type.DOUBLE:
boxedType = KnownTypes.DOUBLE_BOX_TYPE;
break;
case Type.FLOAT:
boxedType = KnownTypes.FLOAT_BOX_TYPE;
break;
case Type.LONG:
boxedType = KnownTypes.LONG_BOX_TYPE;
break;
case Type.INT:
boxedType = KnownTypes.INT_BOX_TYPE;
break;
case Type.SHORT:
boxedType = KnownTypes.SHORT_BOX_TYPE;
break;
case Type.BYTE:
boxedType = KnownTypes.BYTE_BOX_TYPE;
break;
default:
boxedType = null;
break;
}
if (boxedType == null) {
comment("Unkown boxed type, simply casting");
checkCast(type);
} else {
comment("Boxing " + type + " to " + boxedType);
invokeStatic(boxedType, new Method("valueOf", boxedType, new Type[]{type}));
}
}
public void invokeIStatic(Type owner, Method method) {
invokeInsn(Opcodes.INVOKESTATIC, owner, method, true);
}
public void comment(String comment) {
if (BuildMetadata.IS_RELEASE) return;
push("[Comment/Generator] " + comment);
pop();
}
// Taken from GeneratorAdapter
private void invokeInsn(final int opcode, final Type type, final Method method, final boolean isInterface) {
String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
mv.visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor(), isInterface);
}
}