@@ -40,6 +40,10 @@ public class ASMAPI {
40
40
*
41
41
* @param nodes The instructions you want to add
42
42
* @return A new list with the instructions
43
+ *
44
+ * @apiNote Due to a bug in Nashorn, invoking this method from your CoreMod with a very large array (or varargs)
45
+ * will not work due to it being cast to {@code Object[]}. In that case, you will need to wrap this method
46
+ * like this: {@code ASMAPI.listOf(Java.to([...], Java.type('org.objectweb.asm.tree.AbstractInsnNode[]')))}.
43
47
*/
44
48
public static InsnList listOf (AbstractInsnNode ... nodes ) {
45
49
InsnList list = new InsnList ();
@@ -78,6 +82,21 @@ public static boolean insertInsn(MethodNode method, AbstractInsnNode insn, Abstr
78
82
return true ;
79
83
}
80
84
85
+ /**
86
+ * Inserts/replaces an instruction, with respect to the given {@link InsertMode}, on the given index.
87
+ *
88
+ * @param method The method to insert the instruction into
89
+ * @param index The index where the new instruction should be inserted into
90
+ * @param toInsert The instruction to be inserted
91
+ * @param mode How the instruction should be inserted
92
+ * @return {@code true} if the list was inserted, {@code false} otherwise
93
+ */
94
+ public static boolean insertInsn (MethodNode method , int index , AbstractInsnNode toInsert , InsertMode mode ) {
95
+ index = clamp (index , 0 , method .instructions .size ());
96
+ var insn = method .instructions .get (index );
97
+ return insertInsn (method , insn , toInsert , mode );
98
+ }
99
+
81
100
/**
82
101
* Inserts/replaces an instruction, with respect to the given {@link InsertMode}, on the first
83
102
* {@link MethodInsnNode} that matches the parameters of these functions in the method provided. Only the first
@@ -108,6 +127,7 @@ public static boolean insertInsn(MethodNode method, MethodType type, String owne
108
127
* Inserts/replaces an instruction list, with respect to the given {@link InsertMode}, on the given instruction.
109
128
*
110
129
* @param method The method to insert the list into
130
+ * @param insn The instruction where the list should be inserted into
111
131
* @param list The list to be inserted
112
132
* @param mode How the list should be inserted
113
133
* @return {@code true} if the list was inserted, {@code false} otherwise
@@ -126,6 +146,19 @@ public static boolean insertInsnList(MethodNode method, AbstractInsnNode insn, I
126
146
return true ;
127
147
}
128
148
149
+ /**
150
+ * Inserts/replaces an instruction list, with respect to the given {@link InsertMode}, on the given index.
151
+ *
152
+ * @param method The method to insert the list into
153
+ * @param index The index where the list should be inserted into
154
+ * @param list The list to be inserted
155
+ * @param mode How the list should be inserted
156
+ * @return {@code true} if the list was inserted, {@code false} otherwise
157
+ */
158
+ public static boolean insertInsnList (MethodNode method , int index , InsnList list , InsertMode mode ) {
159
+ return insertInsnList (method , method .instructions .get (clamp (index , 0 , method .instructions .size ())), list , mode );
160
+ }
161
+
129
162
/**
130
163
* Inserts/replaces an instruction list, with respect to the given {@link InsertMode}, on the first
131
164
* {@link MethodInsnNode} that matches the parameters of these functions in the method provided. Only the first
@@ -159,7 +192,7 @@ public static boolean insertInsnList(MethodNode method, MethodType type, String
159
192
* @param insn The method call to inject
160
193
*/
161
194
public static void injectMethodCall (MethodNode method , MethodInsnNode insn ) {
162
- method . instructions . insertBefore (method .instructions .getFirst (), insn );
195
+ ASMAPI . insertInsn (method , method .instructions .getFirst (), insn , InsertMode . INSERT_BEFORE );
163
196
}
164
197
165
198
/**
@@ -263,6 +296,18 @@ public int get() {
263
296
return findFirstInstructionAfter (method , opcode , null , startIndex );
264
297
}
265
298
299
+ /**
300
+ * Finds the first instruction with matching opcode after the given start instruction.
301
+ *
302
+ * @param method the method to search in
303
+ * @param opcode the opcode to search for
304
+ * @param startInsn the instruction to start search after (inclusive)
305
+ * @return the found instruction node or {@code null} if none matched after the given index
306
+ */
307
+ public static @ Nullable AbstractInsnNode findFirstInstructionAfter (MethodNode method , int opcode , AbstractInsnNode startInsn ) {
308
+ return findFirstInstructionAfter (method , opcode , method .instructions .indexOf (startInsn ));
309
+ }
310
+
266
311
/**
267
312
* Finds the first instruction with matching instruction type after the given start index.
268
313
*
@@ -275,6 +320,18 @@ public int get() {
275
320
return findFirstInstructionAfter (method , -2 , type , startIndex );
276
321
}
277
322
323
+ /**
324
+ * Finds the first instruction with matching instruction type after the given start instruction.
325
+ *
326
+ * @param method the method to search in
327
+ * @param type the instruction type to search for
328
+ * @param startInsn the instruction to start search after (inclusive)
329
+ * @return the found instruction node or {@code null} if none matched after the given index
330
+ */
331
+ public static @ Nullable AbstractInsnNode findFirstInstructionAfter (MethodNode method , InsnType type , AbstractInsnNode startInsn ) {
332
+ return findFirstInstructionAfter (method , type , method .instructions .indexOf (startInsn ));
333
+ }
334
+
278
335
/**
279
336
* Finds the first instruction with matching opcode and instruction type after the given start index.
280
337
*
@@ -296,6 +353,19 @@ public int get() {
296
353
return null ;
297
354
}
298
355
356
+ /**
357
+ * Finds the first instruction with matching opcode and instruction type after the given start instruction.
358
+ *
359
+ * @param method the method to search in
360
+ * @param opcode the opcode to search for
361
+ * @param type the instruction type to search for
362
+ * @param startInsn the instruction to start search after (inclusive)
363
+ * @return the found instruction node or {@code null} if none matched after the given index
364
+ */
365
+ public static @ Nullable AbstractInsnNode findFirstInstructionAfter (MethodNode method , int opcode , @ Nullable InsnType type , AbstractInsnNode startInsn ) {
366
+ return findFirstInstructionAfter (method , opcode , type , method .instructions .indexOf (startInsn ));
367
+ }
368
+
299
369
/**
300
370
* Finds the first instruction with matching opcode before the given index in reverse search.
301
371
*
@@ -313,6 +383,21 @@ public int get() {
313
383
return findFirstInstructionBefore (method , opcode , null , startIndex );
314
384
}
315
385
386
+ /**
387
+ * Finds the first instruction with matching opcode before the given instruction in reverse search.
388
+ *
389
+ * @param method the method to search in
390
+ * @param opcode the opcode to search for
391
+ * @param startInsn the instruction at which to start searching (inclusive)
392
+ * @return the found instruction node or {@code null} if none matched before the given startIndex
393
+ *
394
+ * @apiNote Since this method is new, it will automatically apply the fixed logic in
395
+ * {@link #findFirstInstructionBefore(MethodNode, int, InsnType, int, boolean)}.
396
+ */
397
+ public static @ Nullable AbstractInsnNode findFirstInstructionBefore (MethodNode method , int opcode , AbstractInsnNode startInsn ) {
398
+ return findFirstInstructionBefore (method , opcode , null , startInsn );
399
+ }
400
+
316
401
/**
317
402
* Finds the first instruction with matching instruction type before the given index in reverse search.
318
403
*
@@ -330,6 +415,21 @@ public int get() {
330
415
return findFirstInstructionBefore (method , -2 , type , startIndex );
331
416
}
332
417
418
+ /**
419
+ * Finds the first instruction with matching instruction type before the given instruction in reverse search.
420
+ *
421
+ * @param method the method to search in
422
+ * @param type the instruction type to search for
423
+ * @param startInsn the index at which to start searching (inclusive)
424
+ * @return the found instruction node or {@code null} if none matched before the given startIndex
425
+ *
426
+ * @apiNote Since this method is new, it will automatically apply the fixed logic in
427
+ * {@link #findFirstInstructionBefore(MethodNode, int, InsnType, int, boolean)}.
428
+ */
429
+ public static @ Nullable AbstractInsnNode findFirstInstructionBefore (MethodNode method , InsnType type , AbstractInsnNode startInsn ) {
430
+ return findFirstInstructionBefore (method , -2 , type , startInsn );
431
+ }
432
+
333
433
/**
334
434
* Finds the first instruction with matching opcode before the given index in reverse search.
335
435
*
@@ -376,6 +476,22 @@ public int get() {
376
476
return findFirstInstructionBefore (method , opCode , type , startIndex , !CoreModEngine .DO_NOT_FIX_INSNBEFORE );
377
477
}
378
478
479
+ /**
480
+ * Finds the first instruction with matching opcode and instruction type before the given instruction in reverse
481
+ * search.
482
+ *
483
+ * @param method the method to search in
484
+ * @param opCode the opcode to search for
485
+ * @param startInsn the instruction at which to start searching (inclusive)
486
+ * @return the found instruction node or {@code null} if none matched before the given startIndex
487
+ *
488
+ * @apiNote Since this method is new, it will automatically apply the fixed logic in
489
+ * {@link #findFirstInstructionBefore(MethodNode, int, InsnType, int, boolean)}.
490
+ */
491
+ public static @ Nullable AbstractInsnNode findFirstInstructionBefore (MethodNode method , int opCode , @ Nullable InsnType type , AbstractInsnNode startInsn ) {
492
+ return findFirstInstructionBefore (method , opCode , type , method .instructions .indexOf (startInsn ), true );
493
+ }
494
+
379
495
/**
380
496
* Finds the first instruction with matching opcode and instruction type before the given index in reverse search.
381
497
*
@@ -414,7 +530,7 @@ public int get() {
414
530
415
531
/**
416
532
* Finds the first method call in the given method matching the given type, owner, name and descriptor after the
417
- * instruction given index.
533
+ * given index.
418
534
*
419
535
* @param method the method to search in
420
536
* @param type the type of method call to search for
@@ -438,6 +554,22 @@ public int get() {
438
554
return null ;
439
555
}
440
556
557
+ /**
558
+ * Finds the first method call in the given method matching the given type, owner, name and descriptor after the
559
+ * given instruction.
560
+ *
561
+ * @param method the method to search in
562
+ * @param type the type of method call to search for
563
+ * @param owner the method call's owner to search for
564
+ * @param name the method call's name
565
+ * @param descriptor the method call's descriptor
566
+ * @param insn the instruction after which to start searching (inclusive)
567
+ * @return the found method call node, {@code null} if none matched after the given index
568
+ */
569
+ public static @ Nullable MethodInsnNode findFirstMethodCallAfter (MethodNode method , MethodType type , String owner , String name , String descriptor , AbstractInsnNode insn ) {
570
+ return findFirstMethodCallAfter (method , type , owner , name , descriptor , method .instructions .indexOf (insn ));
571
+ }
572
+
441
573
/**
442
574
* Finds the first method call in the given method matching the given type, owner, name and descriptor before the
443
575
* given index in reverse search.
@@ -464,6 +596,22 @@ public int get() {
464
596
return null ;
465
597
}
466
598
599
+ /**
600
+ * Finds the first method call in the given method matching the given type, owner, name and descriptor before the
601
+ * given instruction in reverse search.
602
+ *
603
+ * @param method the method to search in
604
+ * @param type the type of method call to search for
605
+ * @param owner the method call's owner to search for
606
+ * @param name the method call's name
607
+ * @param descriptor the method call's descriptor
608
+ * @param insn the instruction at which to start searching (inclusive)
609
+ * @return the found method call node or {@code null} if none matched before the given startIndex
610
+ */
611
+ public static @ Nullable MethodInsnNode findFirstMethodCallBefore (MethodNode method , MethodType type , String owner , String name , String descriptor , AbstractInsnNode insn ) {
612
+ return findFirstMethodCallBefore (method , type , owner , name , descriptor , method .instructions .indexOf (insn ));
613
+ }
614
+
467
615
/**
468
616
* Finds the first field call in the given method matching the given opcode, owner, name and descriptor.
469
617
*
@@ -480,7 +628,7 @@ public int get() {
480
628
481
629
/**
482
630
* Finds the first field call in the given method matching the given opcode, owner, name and descriptor after the
483
- * instruction given index.
631
+ * given index.
484
632
*
485
633
* @param method the method to search in
486
634
* @param opcode the opcode of field call to search for
@@ -503,6 +651,22 @@ public int get() {
503
651
return null ;
504
652
}
505
653
654
+ /**
655
+ * Finds the first field call in the given method matching the given opcode, owner, name and descriptor after the
656
+ * given instruction.
657
+ *
658
+ * @param method the method to search in
659
+ * @param opcode the opcode of field call to search for
660
+ * @param owner the method call's owner to search for
661
+ * @param name the method call's name
662
+ * @param descriptor the method call's descriptor
663
+ * @param startInsn the instruction after which to start searching (inclusive)
664
+ * @return the found method call node, {@code null} if none matched after the given index
665
+ */
666
+ public static @ Nullable FieldInsnNode findFirstFieldCallAfter (MethodNode method , int opcode , String owner , String name , String descriptor , AbstractInsnNode startInsn ) {
667
+ return findFirstFieldCallAfter (method , opcode , owner , name , descriptor , method .instructions .indexOf (startInsn ));
668
+ }
669
+
506
670
/**
507
671
* Finds the first field call in the given method matching the given opcode, owner, name and descriptor before the
508
672
* given index in reverse search.
@@ -528,6 +692,22 @@ public int get() {
528
692
return null ;
529
693
}
530
694
695
+ /**
696
+ * Finds the first field call in the given method matching the given opcode, owner, name and descriptor before the
697
+ * given instruction in reverse search.
698
+ *
699
+ * @param method the method to search in
700
+ * @param opcode the opcode of field call to search for
701
+ * @param owner the method call's owner to search for
702
+ * @param name the method call's name
703
+ * @param descriptor the method call's descriptor
704
+ * @param startInsn the instruction at which to start searching (inclusive)
705
+ * @return the found method call node or {@code null} if none matched before the given startIndex
706
+ */
707
+ public static @ Nullable FieldInsnNode findFirstFieldCallBefore (MethodNode method , int opcode , String owner , String name , String descriptor , AbstractInsnNode startInsn ) {
708
+ return findFirstFieldCallBefore (method , opcode , owner , name , descriptor , method .instructions .indexOf (startInsn ));
709
+ }
710
+
531
711
532
712
/* CREATING AND FINDING METHODS */
533
713
@@ -1105,4 +1285,12 @@ private static String toString(Textifier text) {
1105
1285
pw .flush ();
1106
1286
return sw .toString ();
1107
1287
}
1288
+
1289
+
1290
+ /* MISCELLANEOUS */
1291
+
1292
+ // private because this is really only used to clamp indexes
1293
+ private static int clamp (int value , int min , int max ) {
1294
+ return Math .max (min , Math .min (max , value ));
1295
+ }
1108
1296
}
0 commit comments