package com.linkedin.parseq.lambda;
import java.util.StringJoiner;
import java.util.regex.Pattern;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
class Util {
private static final Pattern LAMBDA_NAME_PATTERN = Pattern.compile("^.*\\$\\$Lambda\\$\\d+$");
/* package private */
static boolean isALambdaClassByName(String name) {
return LAMBDA_NAME_PATTERN.matcher(name.replace('/', '.')).matches();
}
/* package private */
static String extractSimpleName(String fqcn, String separator) {
if (fqcn.contains(separator)) {
return fqcn.substring(fqcn.lastIndexOf(separator) + 1, fqcn.length());
} else {
return fqcn;
}
}
/* package private */
static String getArgumentsInformation(String insnDesc) {
if (insnDesc == null) {
return "";
}
Type methodType = Type.getMethodType(insnDesc);
int argSize = methodType.getArgumentTypes().length;
StringJoiner sj = new StringJoiner(",", "(", ")");
for (int i = 0; i < argSize; i++) {
sj.add("_");
}
return sj.toString();
}
/* package private */
static String getDescriptionForMethodInsnNode(MethodInsnNode methodInstr) {
if (methodInstr.getOpcode() == Opcodes.INVOKESPECIAL && methodInstr.name.equals("<init>")) {
return "new " + Util.extractSimpleName(methodInstr.owner, "/") + "()";
} else {
Type methodType = Type.getMethodType(methodInstr.desc);
int retSize = methodType.getArgumentsAndReturnSizes() & 0x03;
if (retSize > 0) {
return methodInstr.name + Util.getArgumentsInformation(methodInstr.desc);
}
}
return "";
}
/* package private */
static String getDescriptionForTypeInsnNode(TypeInsnNode typeInsnNode) {
AbstractInsnNode nextInsn = typeInsnNode.getNext();
StringJoiner argsDesc = new StringJoiner(",", "(", ")");
while (nextInsn != null) {
if (nextInsn instanceof LdcInsnNode) {
argsDesc.add("_");
} else if (nextInsn.getOpcode() == Opcodes.DUP) {
//ignore
} else {
break;
}
nextInsn = nextInsn.getNext();
}
if (typeInsnNode.getOpcode() == Opcodes.NEW) {
return "new " + Util.extractSimpleName(typeInsnNode.desc, "/") + argsDesc.toString();
}
return "";
}
}