Skip to content

Commit 1de927c

Browse files
committed
ASM-API: Implement java identifiers as helpers
The implementation contains class, method and field identifiers. The class identifier is extendable to provide flexibility for the architecture. The identifiers are helpers since they help us orgnaize what to transform. The identifiers support any class and they're not stricted to Minecraft classes only.
1 parent d96a053 commit 1de927c

4 files changed

Lines changed: 245 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package codes.biscuit.skyblockaddons.asm.api.helper;
2+
3+
import lombok.Getter;
4+
5+
/**
6+
* An identifier for a class to transform
7+
*
8+
* @author iHDeveloper
9+
*/
10+
public abstract class TransformClassHelper {
11+
12+
/**
13+
* @return The name used for the owner of a field or method, or a field type.
14+
*/
15+
public final String getNameAsOwner() {
16+
return "L" + getName() + ";";
17+
}
18+
19+
/**
20+
* @return The name used to identify this class
21+
*/
22+
public String getTransformerName() {
23+
// The regex matches single slash or multiple and replace them with one dot
24+
return getName().replaceAll("(\\/)+", ".");
25+
}
26+
27+
/**
28+
* @return The raw name of the class
29+
*/
30+
public abstract String getName();
31+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package codes.biscuit.skyblockaddons.asm.api.helper;
2+
3+
import jdk.internal.org.objectweb.asm.Opcodes;
4+
import lombok.Getter;
5+
import org.objectweb.asm.tree.FieldInsnNode;
6+
7+
/**
8+
* An identifier for a field to transform
9+
*
10+
* @author iHDeveloper
11+
*/
12+
@Getter
13+
public class TransformFieldHelper {
14+
15+
private final TransformClassHelper owner;
16+
private final String name;
17+
private String type;
18+
19+
/**
20+
* Create a field helper to help the transformation process
21+
*
22+
* @param owner The owner of the field
23+
* @param name The name of the field
24+
* @param type A non-class field type {@link TransformFieldTypes}
25+
*/
26+
public TransformFieldHelper(TransformClassHelper owner, String name, char type) {
27+
this(owner, name, "");
28+
this.type = "" + type;
29+
}
30+
31+
/**
32+
* Create a field helper to help the transformation process
33+
*
34+
* @param owner The owner of the field
35+
* @param name The name of the field
36+
* @param type A class helper if the field type is class
37+
*/
38+
public TransformFieldHelper(TransformClassHelper owner, String name, TransformClassHelper type) {
39+
this(owner, name, type.getNameAsOwner());
40+
}
41+
42+
/**
43+
* Create a field helper to help the transformation process
44+
*
45+
* @param owner The owner of the field
46+
* @param name The name of the field
47+
* @param type The raw name of the class
48+
*/
49+
public TransformFieldHelper(TransformClassHelper owner, String name, String type) {
50+
this.owner = owner;
51+
this.name = name;
52+
this.type = "L" + type + ";";
53+
}
54+
55+
/**
56+
* Generate the get field instruction of the field
57+
*
58+
* @return An instruction node of the get field instruction
59+
*/
60+
public FieldInsnNode createGetInstruction() {
61+
return new FieldInsnNode(Opcodes.GETFIELD, owner.getNameAsOwner(), name, type);
62+
}
63+
64+
/**
65+
* Generate the put instruction of the field
66+
*
67+
* @return An instruction node of the put field instruction
68+
*/
69+
public FieldInsnNode createPutInstruction() {
70+
return new FieldInsnNode(Opcodes.PUTFIELD, owner.getNameAsOwner(), name, type);
71+
}
72+
73+
public boolean equals(FieldInsnNode insnNode) {
74+
return name.equals(insnNode.name) && type.equals(insnNode.desc);
75+
}
76+
77+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package codes.biscuit.skyblockaddons.asm.api.helper;
2+
3+
public final class TransformFieldTypes {
4+
public static final char BYTE = 'B';
5+
public static final char CHAR = 'C';
6+
public static final char DOUBLE = 'D';
7+
public static final char FLOAT = 'F';
8+
public static final char INT = 'I';
9+
public static final char LONG = 'j';
10+
public static final char SHORT = 'S';
11+
public static final char BOOLEAN = 'Z';
12+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package codes.biscuit.skyblockaddons.asm.api.helper;
2+
3+
import lombok.Getter;
4+
import org.objectweb.asm.Opcodes;
5+
import org.objectweb.asm.tree.MethodInsnNode;
6+
import org.objectweb.asm.tree.MethodNode;
7+
8+
/**
9+
* An identifier for a method to transform
10+
*
11+
* @author iHDeveloper
12+
*/
13+
@Getter
14+
public class TransformMethodHelper {
15+
16+
/**
17+
* Represents the constructor of the class
18+
*/
19+
public static final TransformMethodHelper INIT = new TransformMethodHelper("<init>", "<init>");
20+
21+
private final String name;
22+
private String type;
23+
private final String[] parameters;
24+
private final boolean ioException;
25+
26+
/**
27+
* Create a method with name and void as return type
28+
*
29+
* @param name The name of the method
30+
*/
31+
public TransformMethodHelper(String name) {
32+
this(name, null);
33+
}
34+
35+
/**
36+
* Create a method with name and non-class return type
37+
*
38+
* @param name The name of the method
39+
* @param type A non-class field type {@link TransformFieldTypes}
40+
*/
41+
public TransformMethodHelper(String name, char type) {
42+
this(name, "");
43+
this.type = "" + type;
44+
}
45+
46+
/**
47+
* Create a method with name and class as return type
48+
*
49+
* @param name The name of the method
50+
* @param type A class as return type
51+
*/
52+
public TransformMethodHelper(String name, String type) {
53+
this(name, type, new String[0]);
54+
}
55+
56+
/**
57+
* Create a method with name, class as return type and parameters
58+
*
59+
* @param name The name of the method
60+
* @param type A class as return type
61+
* @param parameters The parameters of the method
62+
*/
63+
public TransformMethodHelper(String name, String type, String[] parameters) {
64+
this(name, type, parameters, false);
65+
}
66+
67+
/**
68+
* Create a method with name, class as return type and parameters
69+
*
70+
* @param name The name of the method
71+
* @param type A class as return type
72+
* @param parameters The parameters of the method
73+
* @param ioException Does the method throw an IO exception
74+
*/
75+
public TransformMethodHelper(String name, String type, String[] parameters, boolean ioException) {
76+
this.name = name;
77+
this.type = type == null ? null : "L" + type + ";";
78+
this.parameters = parameters;
79+
this.ioException = ioException;
80+
}
81+
82+
/**
83+
* Generate a assembly method node of the method
84+
*
85+
* @return The generated node of the method
86+
*/
87+
public final MethodNode createMethodNode() {
88+
return new MethodNode(Opcodes.ACC_PUBLIC, name, getDescriptor(), null, getExceptions());
89+
}
90+
91+
public boolean equals(MethodInsnNode insnNode) {
92+
return name.equals(insnNode.name) && getDescriptor().equals(insnNode.desc);
93+
}
94+
95+
public boolean equals(MethodNode node) {
96+
return name.equals(node.name) && (getDescriptor().equals(node.desc) || this == INIT);
97+
}
98+
99+
/**
100+
* Build a descriptor from the method parameters and result
101+
*
102+
* @return Method Descriptor
103+
*/
104+
public String getDescriptor() {
105+
StringBuilder builder = new StringBuilder();
106+
builder.append("(");
107+
for (String param : parameters) {
108+
builder.append(param);
109+
}
110+
builder.append(")");
111+
if (type == null) builder.append("V");
112+
else builder.append(type);
113+
return builder.toString();
114+
}
115+
116+
/**
117+
* Exceptions thrown by the method
118+
*
119+
* @return A list of exceptions
120+
*/
121+
public String[] getExceptions() {
122+
if (ioException) return new String[0];
123+
return new String[] { "java/io/IOException" };
124+
}
125+
}

0 commit comments

Comments
 (0)