diff options
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/ftbsc/lll/tools/DescriptorBuilder.java | 141 | ||||
-rw-r--r-- | src/main/java/ftbsc/lll/tools/InsnSequence.java | 17 |
2 files changed, 158 insertions, 0 deletions
diff --git a/src/main/java/ftbsc/lll/tools/DescriptorBuilder.java b/src/main/java/ftbsc/lll/tools/DescriptorBuilder.java new file mode 100644 index 0000000..5cb6c6f --- /dev/null +++ b/src/main/java/ftbsc/lll/tools/DescriptorBuilder.java @@ -0,0 +1,141 @@ +package ftbsc.lll.tools; + +import jdk.internal.org.objectweb.asm.Type; + +import java.util.ArrayList; + +/** + * Builds a method descriptor for you. + * Parameters must be given in a specific order. + * Return type should always be specified for clarity, but defaults to void. + */ +public class DescriptorBuilder { + /** + * The descriptor of the return type. + */ + private String returnType; + + /** + * The descriptors of the parameters. + */ + private final ArrayList<String> params; + + /** + * Public constructor. + * Initialises default values. + */ + public DescriptorBuilder() { + + this.returnType = Type.getDescriptor(void.class); + this.params = new ArrayList<>(); + } + + /** + * Sets the return type to the given type. + * WARNING: will most likely cause problems if used with objects outside the + * Java SDK. Pass the fully qualified name as a String rather than the Class + * object for non-standard types (such as Minecraft classes). + * @param returnType the Class object corresponding to the return type + * @return the builder's state after the change + */ + public DescriptorBuilder setReturnType(Class<?> returnType) { + this.returnType = Type.getDescriptor(returnType); + return this; + } + + /** + * Sets the return type to the Object specified here as a fully + * qualified name. Example: java.lang.String. + * No validity checks are performed: it's up to the user to ensure the name is correct. + * @param returnType the fully qualified name of the desired Object. + * @return the builder's state after the change + */ + public DescriptorBuilder setReturnType(String returnType) { + return this.setReturnType(returnType, 0); + } + + /** + * Sets the return type to the Object specified here as a fully + * qualified name (example: java.lang.String), with the specified array level. + * No validity checks are performed: it's up to the user to ensure the name is correct. + * @param returnType the fully qualified name of the desired Object. + * @param arrayLevel how many levels of array are there + * (example: String is 0, String[] is 1, String[][] is 2, etc.) + * @return the builder's state after the change + */ + public DescriptorBuilder setReturnType(String returnType, int arrayLevel) { + this.returnType = nameToDescriptor(returnType, arrayLevel); + return this; + } + + /** + * Adds a parameter of the given class type to the method. + * Parameter order matters. + * WARNING: will most likely cause problems if used with objects outside the + * Java SDK. Pass the fully qualified name as a String rather than the Class + * object for non-standard types (such as Minecraft classes). + * @param param the Class object corresponding to the parameter + * @return the builder's state after the change + */ + public DescriptorBuilder addParameter(Class<?> param) { + this.params.add(Type.getDescriptor(param)); + return this; + } + + /** + * Adds a parameter with the type specified by the given fully + * qualified name to the method. Example: java.lang.String. + * Parameter order matters. + * No validity checks are performed: it's up to the user to ensure the name is correct. + * @param param the fully qualified name of the parameter type + * @return the builder's state after the change + */ + public DescriptorBuilder addParameter(String param) { + return this.addParameter(param, 0); + } + + /** + * Adds a parameter with the type specified by the given fully + * qualified name (example: java.lang.String) to the method, with + * the specified array level. + * Parameter order matters. + * No validity checks are performed: it's up to the user to ensure the name is correct. + * @param param the fully qualified name of the parameter type + * @param arrayLevel how many levels of array are there + * (example: String is 0, String[] is 1, String[][] is 2, etc.) + * @return the builder's state after the change + */ + public DescriptorBuilder addParameter(String param, int arrayLevel) { + this.params.add(nameToDescriptor(param, arrayLevel)); + return this; + } + + /** + * Builds the descriptor into a string. + * Example result: int m(Object[] o) -> ([Ljava/lang/Object;)I + * @return the resulting descriptor + */ + public String build() { + StringBuilder sb = new StringBuilder(); + sb.append('('); + for(String p : params) + sb.append(p); + sb.append(')').append(returnType); + return sb.toString(); + } + + /** + * Converts a fully qualified name and array level to a descriptor. + * @param name the fully qualified name of the object type + * @param arrayLevel how many levels of array are there + * (example: String is 0, String[] is 1, String[][] is 2, etc.) + * @return object descriptor + */ + public static String nameToDescriptor(String name, int arrayLevel) { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < arrayLevel; i++) + sb.append('['); + sb.append('L').append(name.replace('.', '/')).append(';'); + return sb.toString(); + } +} diff --git a/src/main/java/ftbsc/lll/tools/InsnSequence.java b/src/main/java/ftbsc/lll/tools/InsnSequence.java index f778590..4afd626 100644 --- a/src/main/java/ftbsc/lll/tools/InsnSequence.java +++ b/src/main/java/ftbsc/lll/tools/InsnSequence.java @@ -13,6 +13,14 @@ import java.util.Objects; public class InsnSequence extends InsnList { /** * Public constructor. + * This creates an empty sequence. + */ + public InsnSequence() { + super(); + } + + /** + * Public constructor. * Must be given two non-null, connected nodes. * @param startNode the starting node of the pattern * @param endNode the first node of the pattern @@ -42,6 +50,15 @@ public class InsnSequence extends InsnList { } /** + * Adds an array of nodes to the list. + * @param nodes the nodes to add + */ + public void add(AbstractInsnNode... nodes) { + for(AbstractInsnNode node : nodes) + super.add(node); + } + + /** * Replaces a node with another one. Mostly used internally. * @param oldNode node to replace * @param newNode new node |