19
19
import java .io .PrintWriter ;
20
20
import java .io .StringWriter ;
21
21
import java .lang .reflect .Modifier ;
22
- import java .util .Iterator ;
23
22
import java .util .ListIterator ;
24
23
import java .util .Objects ;
25
24
import java .util .Optional ;
@@ -33,17 +32,29 @@ public static MethodNode getMethodNode() {
33
32
return new MethodNode (Opcodes .ASM9 );
34
33
}
35
34
36
- // Terribly named method. Should be called "prependMethodCall" or something similar.
37
35
/**
38
36
* Injects a method call to the beginning of the given method.
39
37
*
40
38
* @param node The method to inject the call into
41
39
* @param methodCall The method call to inject
42
40
*/
43
- public static void appendMethodCall (MethodNode node , MethodInsnNode methodCall ) {
41
+ public static void injectMethodCall (MethodNode node , MethodInsnNode methodCall ) {
44
42
node .instructions .insertBefore (node .instructions .getFirst (), methodCall );
45
43
}
46
44
45
+ /**
46
+ * Injects a method call to the beginning of the given method.
47
+ *
48
+ * @param node The method to inject the call into
49
+ * @param methodCall The method call to inject
50
+ *
51
+ * @deprecated Renamed to {@link #injectMethodCall(MethodNode, MethodInsnNode)}
52
+ */
53
+ @ Deprecated (forRemoval = true , since = "5.1" )
54
+ public static void appendMethodCall (MethodNode node , MethodInsnNode methodCall ) {
55
+ injectMethodCall (node , methodCall );
56
+ }
57
+
47
58
/**
48
59
* Signifies the method invocation type. Mirrors "INVOKE-" opcodes from ASM.
49
60
*/
@@ -80,17 +91,17 @@ public static MethodInsnNode buildMethodCall(final String ownerName, final Strin
80
91
}
81
92
82
93
/**
83
- * Signifies the type of number constant for a {@link LdcNumberType }.
94
+ * Signifies the type of number constant for a {@link NumberType }.
84
95
*/
85
- public enum LdcNumberType {
96
+ public enum NumberType {
86
97
INTEGER (Number ::intValue ),
87
98
FLOAT (Number ::floatValue ),
88
99
LONG (Number ::longValue ),
89
100
DOUBLE (Number ::doubleValue );
90
101
91
102
private final Function <Number , Object > mapper ;
92
103
93
- LdcNumberType (Function <Number , Object > mapper ) {
104
+ NumberType (Function <Number , Object > mapper ) {
94
105
this .mapper = mapper ;
95
106
}
96
107
@@ -100,14 +111,29 @@ public Object map(Number number) {
100
111
}
101
112
102
113
/**
103
- * Builds a new {@link LdcInsnNode} with the given number value and type.
114
+ * Casts a given number to a given specific {@link NumberType}. This helps elliviate the problems that comes with JavaScript's
115
+ * ambiguous number system.
116
+ * <p>
117
+ * The result is returned as an {@link Object} so it can be used as a value in various instructions that require
118
+ * values.
119
+ *
120
+ * @param value The number to cast
121
+ * @param type The type of number to cast to
122
+ * @return The casted number
123
+ */
124
+ public static Object castNumber (final Number value , final NumberType type ) {
125
+ return type .map (value );
126
+ }
127
+
128
+ /**
129
+ * Builds a new {@link LdcInsnNode} with the given number value and {@link NumberType}.
104
130
*
105
131
* @param value The number value
106
132
* @param type The type of the number
107
133
* @return The built LDC node
108
134
*/
109
- public static LdcInsnNode buildNumberLdcInsnNode (final Number value , final LdcNumberType type ) {
110
- return new LdcInsnNode (type . map (value ));
135
+ public static LdcInsnNode buildNumberLdcInsnNode (final Number value , final NumberType type ) {
136
+ return new LdcInsnNode (castNumber (value , type ));
111
137
}
112
138
113
139
/**
@@ -361,35 +387,42 @@ public static MethodInsnNode findFirstMethodCallBefore(MethodNode method, Method
361
387
* in the method provided. Only the first node matching is targeted, all other matches are ignored.
362
388
*
363
389
* @param method The method where you want to find the node
364
- * @param type The type of the old method node.
365
- * @param owner The owner of the old method node.
366
- * @param name The name of the old method node. You may want to use {@link #mapMethod(String)} if this is a srg
367
- * name
368
- * @param desc The desc of the old method node.
390
+ * @param type The type of the old method node
391
+ * @param owner The owner of the old method node
392
+ * @param name The name of the old method node (you may want to use {@link #mapMethod(String)} if this is a srg
393
+ * name)
394
+ * @param desc The desc of the old method node
369
395
* @param list The list that should be inserted
370
396
* @param mode How the given code should be inserted
371
- * @return True if the node was found, false otherwise
397
+ * @return True if the node was found and the list was inserted , false otherwise
372
398
*/
373
399
public static boolean insertInsnList (MethodNode method , MethodType type , String owner , String name , String desc , InsnList list , InsertMode mode ) {
374
- Iterator <AbstractInsnNode > nodeIterator = method .instructions .iterator ();
375
- int opcode = type .toOpcode ();
376
- while (nodeIterator .hasNext ()) {
377
- AbstractInsnNode next = nodeIterator .next ();
378
- if (next .getOpcode () == opcode ) {
379
- MethodInsnNode castedNode = (MethodInsnNode ) next ;
380
- if (castedNode .owner .equals (owner ) && castedNode .name .equals (name ) && castedNode .desc .equals (desc )) {
381
- if (mode == InsertMode .INSERT_BEFORE )
382
- method .instructions .insertBefore (next , list );
383
- else
384
- method .instructions .insert (next , list );
385
-
386
- if (mode == InsertMode .REMOVE_ORIGINAL )
387
- nodeIterator .remove ();
388
- return true ;
389
- }
390
- }
391
- }
392
- return false ;
400
+ var insn = findFirstMethodCall (method , type , owner , name , desc );
401
+ if (insn == null ) return false ;
402
+
403
+ return insertInsnList (method , insn , list , mode );
404
+ }
405
+
406
+ /**
407
+ * Inserts/replaces a list after/before the given instruction.
408
+ *
409
+ * @param method The method where you want to insert the list
410
+ * @param list The list that should be inserted
411
+ * @param mode How the given code should be inserted
412
+ * @return True if the list was inserted, false otherwise
413
+ */
414
+ public static boolean insertInsnList (MethodNode method , AbstractInsnNode insn , InsnList list , InsertMode mode ) {
415
+ if (!method .instructions .contains (insn )) return false ;
416
+
417
+ if (mode == InsertMode .INSERT_BEFORE )
418
+ method .instructions .insertBefore (insn , list );
419
+ else
420
+ method .instructions .insert (insn , list );
421
+
422
+ if (mode == InsertMode .REMOVE_ORIGINAL )
423
+ method .instructions .remove (insn );
424
+
425
+ return true ;
393
426
}
394
427
395
428
/**
0 commit comments