summaryrefslogtreecommitdiff
path: root/asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java')
-rw-r--r--asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java b/asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java
new file mode 100644
index 00000000..c5ca9134
--- /dev/null
+++ b/asm-commons/src/test/java/org/objectweb/asm/commons/GeneratorAdapterTest.java
@@ -0,0 +1,1259 @@
+// ASM: a very small and fast Java bytecode manipulation framework
+// Copyright (c) 2000-2011 INRIA, France Telecom
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+package org.objectweb.asm.commons;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.objectweb.asm.commons.GeneratorAdapter.EQ;
+import static org.objectweb.asm.commons.GeneratorAdapter.GE;
+import static org.objectweb.asm.commons.GeneratorAdapter.GT;
+import static org.objectweb.asm.commons.GeneratorAdapter.LE;
+import static org.objectweb.asm.commons.GeneratorAdapter.LT;
+import static org.objectweb.asm.commons.GeneratorAdapter.NE;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.util.Textifier;
+import org.objectweb.asm.util.TraceMethodVisitor;
+
+/**
+ * Unit tests for {@link GeneratorAdapter}.
+ *
+ * @author Eric Bruneton
+ */
+class GeneratorAdapterTest {
+
+ private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
+
+ @Test
+ void testConstructor_illegalState() {
+ Executable constructor =
+ () -> new GeneratorAdapter(new MethodNode(), Opcodes.ACC_PUBLIC, "name", "()V") {};
+
+ assertThrows(IllegalStateException.class, constructor);
+ }
+
+ @Test
+ void testConstructor_emptyDescriptor() {
+ GeneratorAdapter generatorAdapter =
+ new GeneratorAdapter(new MethodNode(), Opcodes.ACC_PUBLIC, "name", "()V");
+
+ assertEquals(Opcodes.ACC_PUBLIC, generatorAdapter.getAccess());
+ assertEquals("name", generatorAdapter.getName());
+ assertEquals(Type.VOID_TYPE, generatorAdapter.getReturnType());
+ assertArrayEquals(new Type[0], generatorAdapter.getArgumentTypes());
+ }
+
+ @Test
+ void testConstructor_basicDescriptor() {
+ GeneratorAdapter generatorAdapter =
+ new GeneratorAdapter(new MethodNode(), Opcodes.ACC_PRIVATE, "m", "(I)F");
+
+ assertEquals(Opcodes.ACC_PRIVATE, generatorAdapter.getAccess());
+ assertEquals("m", generatorAdapter.getName());
+ assertEquals(Type.FLOAT_TYPE, generatorAdapter.getReturnType());
+ assertArrayEquals(new Type[] {Type.INT_TYPE}, generatorAdapter.getArgumentTypes());
+ }
+
+ @Test
+ void testConstructor_withClassVisitorAndExceptions() {
+ ClassNode classNode = new ClassNode();
+
+ GeneratorAdapter generatorAdapter =
+ new GeneratorAdapter(
+ Opcodes.ACC_PUBLIC,
+ new Method("name", "()V"),
+ "()V",
+ new Type[] {Type.getObjectType("java/lang/Exception")},
+ classNode);
+
+ assertEquals(Opcodes.ACC_PUBLIC, generatorAdapter.getAccess());
+ assertEquals("name", generatorAdapter.getName());
+ assertEquals(Type.VOID_TYPE, generatorAdapter.getReturnType());
+ assertArrayEquals(new Type[0], generatorAdapter.getArgumentTypes());
+ MethodNode methodNode = classNode.methods.get(0);
+ assertEquals(Opcodes.ACC_PUBLIC, methodNode.access);
+ assertEquals("name", methodNode.name);
+ assertEquals("()V", methodNode.desc);
+ assertEquals(Arrays.asList("java/lang/Exception"), methodNode.exceptions);
+ }
+
+ @Test
+ void testConstructor_withClassVisitorAndNoExceptions() {
+ ClassNode classNode = new ClassNode();
+
+ GeneratorAdapter generatorAdapter =
+ new GeneratorAdapter(Opcodes.ACC_PUBLIC, new Method("name", "()V"), "()V", null, classNode);
+
+ assertEquals(Opcodes.ACC_PUBLIC, generatorAdapter.getAccess());
+ assertEquals("name", generatorAdapter.getName());
+ assertEquals(Type.VOID_TYPE, generatorAdapter.getReturnType());
+ assertArrayEquals(new Type[0], generatorAdapter.getArgumentTypes());
+ MethodNode methodNode = classNode.methods.get(0);
+ assertEquals(Opcodes.ACC_PUBLIC, methodNode.access);
+ assertEquals("name", methodNode.name);
+ assertEquals("()V", methodNode.desc);
+ assertEquals(Arrays.asList(), methodNode.exceptions);
+ }
+
+ @Test
+ void testPush_boolean() {
+ assertEquals("ICONST_0", new Generator().push(false));
+ assertEquals("ICONST_1", new Generator().push(true));
+ }
+
+ @Test
+ void testPush_int() {
+ assertEquals("LDC -32769", new Generator().push(-32769));
+ assertEquals("SIPUSH -32768", new Generator().push(-32768));
+ assertEquals("BIPUSH -128", new Generator().push(-128));
+ assertEquals("ICONST_M1", new Generator().push(-1));
+ assertEquals("ICONST_0", new Generator().push(0));
+ assertEquals("ICONST_1", new Generator().push(1));
+ assertEquals("ICONST_2", new Generator().push(2));
+ assertEquals("ICONST_3", new Generator().push(3));
+ assertEquals("ICONST_4", new Generator().push(4));
+ assertEquals("ICONST_5", new Generator().push(5));
+ assertEquals("BIPUSH 6", new Generator().push(6));
+ assertEquals("BIPUSH 127", new Generator().push(127));
+ assertEquals("SIPUSH 128", new Generator().push(128));
+ assertEquals("SIPUSH 32767", new Generator().push(32767));
+ assertEquals("LDC 32768", new Generator().push(32768));
+ }
+
+ @Test
+ void testPush_long() {
+ assertEquals("LCONST_0", new Generator().push(0L));
+ assertEquals("LCONST_1", new Generator().push(1L));
+ assertEquals("LDC 2", new Generator().push(2L));
+ }
+
+ @Test
+ void testPush_float() {
+ assertEquals("FCONST_0", new Generator().push(0.0f));
+ assertEquals("FCONST_1", new Generator().push(1.0f));
+ assertEquals("FCONST_2", new Generator().push(2.0f));
+ assertEquals("LDC 3.0", new Generator().push(3.0f));
+ }
+
+ @Test
+ void testPush_double() {
+ assertEquals("DCONST_0", new Generator().push(0.0));
+ assertEquals("DCONST_1", new Generator().push(1.0));
+ assertEquals("LDC 2.0", new Generator().push(2.0));
+ }
+
+ @Test
+ void testPush_string() {
+ assertEquals("ACONST_NULL", new Generator().push((String) null));
+ assertEquals("LDC \"string\"", new Generator().push("string"));
+ }
+
+ @Test
+ void testPush_type() {
+ assertEquals("ACONST_NULL", new Generator().push((Type) null));
+ assertEquals(
+ "GETSTATIC java/lang/Boolean.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.BOOLEAN_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Character.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.CHAR_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Byte.TYPE : Ljava/lang/Class;", new Generator().push(Type.BYTE_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Short.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.SHORT_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Integer.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.INT_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Float.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.FLOAT_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Long.TYPE : Ljava/lang/Class;", new Generator().push(Type.LONG_TYPE));
+ assertEquals(
+ "GETSTATIC java/lang/Double.TYPE : Ljava/lang/Class;",
+ new Generator().push(Type.DOUBLE_TYPE));
+ assertEquals("LDC Ljava/lang/Object;.class", new Generator().push(OBJECT_TYPE));
+ assertEquals("LDC [I.class", new Generator().push(Type.getObjectType("[I")));
+ }
+
+ @Test
+ void testPush_handle() {
+ assertEquals("ACONST_NULL", new Generator().push((Handle) null));
+ assertEquals(
+ "LDC pkg/Owner.nameI (2)",
+ new Generator().push(new Handle(Opcodes.H_GETSTATIC, "pkg/Owner", "name", "I", false)));
+ }
+
+ @Test
+ void testLoadThis() {
+ assertEquals("ALOAD 0", new Generator().loadThis());
+ }
+
+ @Test
+ void testLoadThis_illegalState() {
+ Generator generator = new Generator(Opcodes.ACC_STATIC, "m", "()V");
+
+ Executable loadThis = () -> generator.loadThis();
+
+ assertThrows(IllegalStateException.class, loadThis);
+ }
+
+ @Test
+ void testLoadArg() {
+ assertEquals("ILOAD 1", new Generator(Opcodes.ACC_PUBLIC, "m", "(I)V").loadArg(0));
+ assertEquals("LLOAD 0", new Generator(Opcodes.ACC_STATIC, "m", "(J)V").loadArg(0));
+ assertEquals("FLOAD 2", new Generator(Opcodes.ACC_STATIC, "m", "(JF)V").loadArg(1));
+ }
+
+ @Test
+ void testLoadArgs() {
+ assertEquals("LLOAD 2", new Generator(Opcodes.ACC_PUBLIC, "m", "(IJFD)V").loadArgs(1, 1));
+ assertEquals(
+ "ILOAD 0 LLOAD 1 FLOAD 3 DLOAD 4",
+ new Generator(Opcodes.ACC_STATIC, "m", "(IJFD)V").loadArgs());
+ }
+
+ @Test
+ void testLoadArgArray() {
+ assertEquals(
+ "BIPUSH 9 ANEWARRAY java/lang/Object "
+ + "DUP ICONST_0 ILOAD 1 NEW java/lang/Boolean DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Boolean.<init> (Z)V AASTORE "
+ + "DUP ICONST_1 ILOAD 2 NEW java/lang/Byte DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Byte.<init> (B)V AASTORE "
+ + "DUP ICONST_2 ILOAD 3 NEW java/lang/Character DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Character.<init> (C)V AASTORE "
+ + "DUP ICONST_3 ILOAD 4 NEW java/lang/Short DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Short.<init> (S)V AASTORE "
+ + "DUP ICONST_4 ILOAD 5 NEW java/lang/Integer DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Integer.<init> (I)V AASTORE "
+ + "DUP ICONST_5 LLOAD 6 NEW java/lang/Long DUP_X2 DUP_X2 POP"
+ + " INVOKESPECIAL java/lang/Long.<init> (J)V AASTORE "
+ + "DUP BIPUSH 6 FLOAD 8 NEW java/lang/Float DUP_X1 SWAP"
+ + " INVOKESPECIAL java/lang/Float.<init> (F)V AASTORE "
+ + "DUP BIPUSH 7 DLOAD 9 NEW java/lang/Double DUP_X2 DUP_X2 POP"
+ + " INVOKESPECIAL java/lang/Double.<init> (D)V AASTORE "
+ + "DUP BIPUSH 8 ALOAD 11 AASTORE",
+ new Generator(Opcodes.ACC_PUBLIC, "m", "(ZBCSIJFDLjava/lang/Object;)V").loadArgArray());
+ }
+
+ @Test
+ void testStoreArg() {
+ assertEquals("ISTORE 1", new Generator(Opcodes.ACC_PUBLIC, "m", "(I)V").storeArg(0));
+ assertEquals("LSTORE 0", new Generator(Opcodes.ACC_STATIC, "m", "(J)V").storeArg(0));
+ assertEquals("FSTORE 2", new Generator(Opcodes.ACC_STATIC, "m", "(JF)V").storeArg(1));
+ }
+
+ @Test
+ void testNewLocal() {
+ Generator generator = new Generator();
+
+ int local = generator.newLocal(Type.FLOAT_TYPE);
+
+ assertEquals(Type.FLOAT_TYPE, generator.getLocalType(local));
+ }
+
+ @Test
+ void testLoadLocal() {
+ Generator generator = new Generator();
+ int local = generator.newLocal(Type.FLOAT_TYPE);
+
+ String loadLocal = generator.loadLocal(local);
+
+ assertEquals("FLOAD 1", loadLocal);
+ }
+
+ @Test
+ void testLoadLocal_withType() {
+ Generator generator = new Generator();
+ int local = generator.newLocal(Type.FLOAT_TYPE);
+
+ String loadLocal = generator.loadLocal(local, Type.INT_TYPE);
+
+ assertEquals("ILOAD 1", loadLocal);
+ assertEquals(Type.INT_TYPE, generator.getLocalType(local));
+ }
+
+ @Test
+ void testStoreLocal() {
+ Generator generator = new Generator();
+ int local = generator.newLocal(Type.FLOAT_TYPE);
+
+ String storeLocal = generator.storeLocal(local);
+
+ assertEquals("FSTORE 1", storeLocal);
+ }
+
+ @Test
+ void testStoreLocal_withType() {
+ Generator generator = new Generator();
+ int local = generator.newLocal(Type.FLOAT_TYPE);
+
+ String storeLocal = generator.storeLocal(local, Type.INT_TYPE);
+
+ assertEquals("ISTORE 1", storeLocal);
+ assertEquals(Type.INT_TYPE, generator.getLocalType(local));
+ }
+
+ @Test
+ void testArrayLoad() {
+ assertEquals("IALOAD", new Generator().arrayLoad(Type.INT_TYPE));
+ assertEquals("LALOAD", new Generator().arrayLoad(Type.LONG_TYPE));
+ }
+
+ @Test
+ void testArrayStore() {
+ assertEquals("IASTORE", new Generator().arrayStore(Type.INT_TYPE));
+ assertEquals("LASTORE", new Generator().arrayStore(Type.LONG_TYPE));
+ }
+
+ @Test
+ void testPop() {
+ assertEquals("POP", new Generator().pop());
+ }
+
+ @Test
+ void testPop2() {
+ assertEquals("POP2", new Generator().pop2());
+ }
+
+ @Test
+ void testDup() {
+ assertEquals("DUP", new Generator().dup());
+ }
+
+ @Test
+ void testDup2() {
+ assertEquals("DUP2", new Generator().dup2());
+ }
+
+ @Test
+ void testDupX1() {
+ assertEquals("DUP_X1", new Generator().dupX1());
+ }
+
+ @Test
+ void testDupX2() {
+ assertEquals("DUP_X2", new Generator().dupX2());
+ }
+
+ @Test
+ void testDup2X1() {
+ assertEquals("DUP2_X1", new Generator().dup2X1());
+ }
+
+ @Test
+ void testDup2X2() {
+ assertEquals("DUP2_X2", new Generator().dup2X2());
+ }
+
+ @Test
+ void testSwap() {
+ assertEquals("SWAP", new Generator().swap());
+ assertEquals("SWAP", new Generator().swap(Type.INT_TYPE, Type.INT_TYPE));
+ assertEquals("DUP_X2 POP", new Generator().swap(Type.LONG_TYPE, Type.INT_TYPE));
+ assertEquals("DUP2_X1 POP2", new Generator().swap(Type.INT_TYPE, Type.LONG_TYPE));
+ assertEquals("DUP2_X2 POP2", new Generator().swap(Type.LONG_TYPE, Type.LONG_TYPE));
+ }
+
+ @Test
+ void testMath() {
+ assertEquals("IADD", new Generator().math(GeneratorAdapter.ADD, Type.INT_TYPE));
+ assertEquals("FSUB", new Generator().math(GeneratorAdapter.SUB, Type.FLOAT_TYPE));
+ assertEquals("LMUL", new Generator().math(GeneratorAdapter.MUL, Type.LONG_TYPE));
+ assertEquals("DDIV", new Generator().math(GeneratorAdapter.DIV, Type.DOUBLE_TYPE));
+ assertEquals("IREM", new Generator().math(GeneratorAdapter.REM, Type.INT_TYPE));
+ assertEquals("LNEG", new Generator().math(GeneratorAdapter.NEG, Type.LONG_TYPE));
+ assertEquals("ISHL", new Generator().math(GeneratorAdapter.SHL, Type.INT_TYPE));
+ assertEquals("LSHR", new Generator().math(GeneratorAdapter.SHR, Type.LONG_TYPE));
+ assertEquals("IUSHR", new Generator().math(GeneratorAdapter.USHR, Type.INT_TYPE));
+ assertEquals("LAND", new Generator().math(GeneratorAdapter.AND, Type.LONG_TYPE));
+ assertEquals("IOR", new Generator().math(GeneratorAdapter.OR, Type.INT_TYPE));
+ assertEquals("LXOR", new Generator().math(GeneratorAdapter.XOR, Type.LONG_TYPE));
+ }
+
+ @Test
+ void testNot() {
+ assertEquals("ICONST_1 IXOR", new Generator().not());
+ }
+
+ @Test
+ void testIinc() {
+ assertEquals("IINC 3 5", new Generator().iinc(3, 5));
+ }
+
+ @Test
+ void testCast() {
+ assertEquals("", new Generator().cast(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE));
+ assertEquals("D2F", new Generator().cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE));
+ assertEquals("D2L", new Generator().cast(Type.DOUBLE_TYPE, Type.LONG_TYPE));
+ assertEquals("D2I", new Generator().cast(Type.DOUBLE_TYPE, Type.INT_TYPE));
+ assertEquals("D2I I2B", new Generator().cast(Type.DOUBLE_TYPE, Type.BYTE_TYPE));
+ assertEquals("F2D", new Generator().cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE));
+ assertEquals("", new Generator().cast(Type.FLOAT_TYPE, Type.FLOAT_TYPE));
+ assertEquals("F2L", new Generator().cast(Type.FLOAT_TYPE, Type.LONG_TYPE));
+ assertEquals("F2I", new Generator().cast(Type.FLOAT_TYPE, Type.INT_TYPE));
+ assertEquals("F2I I2B", new Generator().cast(Type.FLOAT_TYPE, Type.BYTE_TYPE));
+ assertEquals("L2D", new Generator().cast(Type.LONG_TYPE, Type.DOUBLE_TYPE));
+ assertEquals("L2F", new Generator().cast(Type.LONG_TYPE, Type.FLOAT_TYPE));
+ assertEquals("", new Generator().cast(Type.LONG_TYPE, Type.LONG_TYPE));
+ assertEquals("L2I", new Generator().cast(Type.LONG_TYPE, Type.INT_TYPE));
+ assertEquals("L2I I2B", new Generator().cast(Type.LONG_TYPE, Type.BYTE_TYPE));
+ assertEquals("I2D", new Generator().cast(Type.INT_TYPE, Type.DOUBLE_TYPE));
+ assertEquals("I2F", new Generator().cast(Type.INT_TYPE, Type.FLOAT_TYPE));
+ assertEquals("I2L", new Generator().cast(Type.INT_TYPE, Type.LONG_TYPE));
+ assertEquals("", new Generator().cast(Type.INT_TYPE, Type.INT_TYPE));
+ assertEquals("I2B", new Generator().cast(Type.INT_TYPE, Type.BYTE_TYPE));
+ assertEquals("I2C", new Generator().cast(Type.INT_TYPE, Type.CHAR_TYPE));
+ assertEquals("I2S", new Generator().cast(Type.INT_TYPE, Type.SHORT_TYPE));
+ assertEquals("", new Generator().cast(Type.BYTE_TYPE, Type.INT_TYPE));
+ assertEquals("", new Generator().cast(Type.SHORT_TYPE, Type.INT_TYPE));
+ }
+
+ @Test
+ void testCast_fromVoid() {
+ Executable cast = () -> new Generator().cast(Type.VOID_TYPE, Type.INT_TYPE);
+
+ assertThrows(IllegalArgumentException.class, cast);
+ }
+
+ @Test
+ void testCast_toVoid() {
+ Executable cast = () -> new Generator().cast(Type.INT_TYPE, Type.VOID_TYPE);
+
+ assertThrows(IllegalArgumentException.class, cast);
+ }
+
+ @Test
+ void testBox() {
+ assertEquals("", new Generator().box(OBJECT_TYPE));
+ assertEquals("", new Generator().box(Type.getObjectType("[I")));
+ assertEquals("ACONST_NULL", new Generator().box(Type.VOID_TYPE));
+ assertEquals(
+ "NEW java/lang/Boolean DUP_X1 SWAP INVOKESPECIAL java/lang/Boolean.<init> (Z)V",
+ new Generator().box(Type.BOOLEAN_TYPE));
+ assertEquals(
+ "NEW java/lang/Byte DUP_X1 SWAP INVOKESPECIAL java/lang/Byte.<init> (B)V",
+ new Generator().box(Type.BYTE_TYPE));
+ assertEquals(
+ "NEW java/lang/Character DUP_X1 SWAP INVOKESPECIAL java/lang/Character.<init> (C)V",
+ new Generator().box(Type.CHAR_TYPE));
+ assertEquals(
+ "NEW java/lang/Short DUP_X1 SWAP INVOKESPECIAL java/lang/Short.<init> (S)V",
+ new Generator().box(Type.SHORT_TYPE));
+ assertEquals(
+ "NEW java/lang/Integer DUP_X1 SWAP INVOKESPECIAL java/lang/Integer.<init> (I)V",
+ new Generator().box(Type.INT_TYPE));
+ assertEquals(
+ "NEW java/lang/Long DUP_X2 DUP_X2 POP INVOKESPECIAL java/lang/Long.<init> (J)V",
+ new Generator().box(Type.LONG_TYPE));
+ assertEquals(
+ "NEW java/lang/Float DUP_X1 SWAP INVOKESPECIAL java/lang/Float.<init> (F)V",
+ new Generator().box(Type.FLOAT_TYPE));
+ assertEquals(
+ "NEW java/lang/Double DUP_X2 DUP_X2 POP INVOKESPECIAL java/lang/Double.<init> (D)V",
+ new Generator().box(Type.DOUBLE_TYPE));
+ }
+
+ @Test
+ void testValueOf() {
+ assertEquals("", new Generator().valueOf(OBJECT_TYPE));
+ assertEquals("", new Generator().valueOf(Type.getType("[I")));
+ assertEquals("ACONST_NULL", new Generator().valueOf(Type.VOID_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;",
+ new Generator().valueOf(Type.BOOLEAN_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Byte.valueOf (B)Ljava/lang/Byte;",
+ new Generator().valueOf(Type.BYTE_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Character.valueOf (C)Ljava/lang/Character;",
+ new Generator().valueOf(Type.CHAR_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Short.valueOf (S)Ljava/lang/Short;",
+ new Generator().valueOf(Type.SHORT_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;",
+ new Generator().valueOf(Type.INT_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;",
+ new Generator().valueOf(Type.LONG_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;",
+ new Generator().valueOf(Type.FLOAT_TYPE));
+ assertEquals(
+ "INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;",
+ new Generator().valueOf(Type.DOUBLE_TYPE));
+ }
+
+ @Test
+ void testUnbox() {
+ assertEquals("", new Generator().unbox(Type.VOID_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Boolean INVOKEVIRTUAL java/lang/Boolean.booleanValue ()Z",
+ new Generator().unbox(Type.BOOLEAN_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.intValue ()I",
+ new Generator().unbox(Type.BYTE_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Character INVOKEVIRTUAL java/lang/Character.charValue ()C",
+ new Generator().unbox(Type.CHAR_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.intValue ()I",
+ new Generator().unbox(Type.SHORT_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.intValue ()I",
+ new Generator().unbox(Type.INT_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.longValue ()J",
+ new Generator().unbox(Type.LONG_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.floatValue ()F",
+ new Generator().unbox(Type.FLOAT_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number INVOKEVIRTUAL java/lang/Number.doubleValue ()D",
+ new Generator().unbox(Type.DOUBLE_TYPE));
+ assertEquals("", new Generator().unbox(OBJECT_TYPE));
+ assertEquals(
+ "CHECKCAST java/lang/Number",
+ new Generator().unbox(Type.getObjectType("java/lang/Number")));
+ assertEquals("CHECKCAST [I", new Generator().unbox(Type.getType("[I")));
+ }
+
+ @Test
+ void testIfCmp() throws GeneratorException {
+ assertEquals("IF_ICMPEQ L0", new Generator().ifCmp(Type.INT_TYPE, EQ, new Label()));
+ assertEquals("IF_ICMPNE L0", new Generator().ifCmp(Type.INT_TYPE, NE, new Label()));
+ assertEquals("IF_ICMPGE L0", new Generator().ifCmp(Type.INT_TYPE, GE, new Label()));
+ assertEquals("IF_ICMPGT L0", new Generator().ifCmp(Type.INT_TYPE, GT, new Label()));
+ assertEquals("IF_ICMPLE L0", new Generator().ifCmp(Type.INT_TYPE, LE, new Label()));
+ assertEquals("IF_ICMPLT L0", new Generator().ifCmp(Type.INT_TYPE, LT, new Label()));
+ assertEquals("LCMP IFGE L0", new Generator().ifCmp(Type.LONG_TYPE, GE, new Label()));
+ assertEquals("FCMPL IFGE L0", new Generator().ifCmp(Type.FLOAT_TYPE, GE, new Label()));
+ assertEquals("FCMPL IFGT L0", new Generator().ifCmp(Type.FLOAT_TYPE, GT, new Label()));
+ assertEquals("FCMPG IFLE L0", new Generator().ifCmp(Type.FLOAT_TYPE, LE, new Label()));
+ assertEquals("FCMPG IFLT L0", new Generator().ifCmp(Type.FLOAT_TYPE, LT, new Label()));
+ assertEquals("DCMPL IFGE L0", new Generator().ifCmp(Type.DOUBLE_TYPE, GE, new Label()));
+ assertEquals("DCMPL IFGT L0", new Generator().ifCmp(Type.DOUBLE_TYPE, GT, new Label()));
+ assertEquals("DCMPG IFLE L0", new Generator().ifCmp(Type.DOUBLE_TYPE, LE, new Label()));
+ assertEquals("DCMPG IFLT L0", new Generator().ifCmp(Type.DOUBLE_TYPE, LT, new Label()));
+ assertEquals("IF_ACMPEQ L0", new Generator().ifCmp(OBJECT_TYPE, EQ, new Label()));
+ assertEquals("IF_ACMPNE L0", new Generator().ifCmp(OBJECT_TYPE, NE, new Label()));
+ assertEquals("IF_ACMPEQ L0", new Generator().ifCmp(Type.getType("[I"), EQ, new Label()));
+ assertEquals("IF_ACMPNE L0", new Generator().ifCmp(Type.getType("[I"), NE, new Label()));
+ assertThrows(
+ GeneratorException.class, () -> new Generator().ifCmp(OBJECT_TYPE, GE, new Label()));
+ assertThrows(
+ GeneratorException.class, () -> new Generator().ifCmp(Type.getType("[I"), GE, new Label()));
+ assertThrows(
+ GeneratorException.class, () -> new Generator().ifCmp(Type.INT_TYPE, 0, new Label()));
+ }
+
+ @Test
+ void testMark() {
+ assertEquals("L0", new Generator().mark(new Label()));
+ }
+
+ @Test
+ void testIfICmp() throws GeneratorException {
+ assertEquals("IF_ICMPEQ L0", new Generator().ifICmp(EQ, new Label()));
+ assertEquals("IF_ICMPNE L0", new Generator().ifICmp(NE, new Label()));
+ assertEquals("IF_ICMPGE L0", new Generator().ifICmp(GE, new Label()));
+ assertEquals("IF_ICMPGT L0", new Generator().ifICmp(GT, new Label()));
+ assertEquals("IF_ICMPLE L0", new Generator().ifICmp(LE, new Label()));
+ assertEquals("IF_ICMPLT L0", new Generator().ifICmp(LT, new Label()));
+ assertThrows(GeneratorException.class, () -> new Generator().ifICmp(0, new Label()));
+ }
+
+ @Test
+ void testIfZCmp() {
+ assertEquals("IFEQ L0", new Generator().ifZCmp(EQ, new Label()));
+ assertEquals("IFNE L0", new Generator().ifZCmp(NE, new Label()));
+ assertEquals("IFGE L0", new Generator().ifZCmp(GE, new Label()));
+ assertEquals("IFGT L0", new Generator().ifZCmp(GT, new Label()));
+ assertEquals("IFLE L0", new Generator().ifZCmp(LE, new Label()));
+ assertEquals("IFLT L0", new Generator().ifZCmp(LT, new Label()));
+ }
+
+ @Test
+ void testIfNull() {
+ assertEquals("IFNULL L0", new Generator().ifNull(new Label()));
+ }
+
+ @Test
+ void testIfNonNull() {
+ assertEquals("IFNONNULL L0", new Generator().ifNonNull(new Label()));
+ }
+
+ @Test
+ void testGoto() {
+ Generator generator = new Generator();
+ Label label = generator.newLabel();
+
+ String goTo = generator.goTo(label);
+
+ assertEquals("GOTO L0", goTo);
+ }
+
+ @Test
+ void testTableSwitch() throws GeneratorException {
+ assertEquals("L0 ICONST_M1 L1", new Generator().tableSwitch(new int[0]));
+ assertEquals(
+ "TABLESWITCH\n"
+ + " 0: L0\n"
+ + " 1: L1\n"
+ + " default: L2 L0 ICONST_0 L1 ICONST_1 L2 ICONST_M1 L3",
+ new Generator().tableSwitch(new int[] {0, 1}));
+ assertEquals(
+ "LOOKUPSWITCH\n"
+ + " 0: L0\n"
+ + " 1: L1\n"
+ + " default: L2 L0 ICONST_0 L1 ICONST_1 L2 ICONST_M1 L3",
+ new Generator().tableSwitch(new int[] {0, 1}, false));
+ assertEquals(
+ "LOOKUPSWITCH\n"
+ + " 0: L0\n"
+ + " 4: L1\n"
+ + " default: L2 L0 ICONST_0 L1 ICONST_4 L2 ICONST_M1 L3",
+ new Generator().tableSwitch(new int[] {0, 4}));
+ assertEquals(
+ "TABLESWITCH\n"
+ + " 0: L0\n"
+ + " 1: L1\n"
+ + " 2: L1\n"
+ + " 3: L1\n"
+ + " 4: L2\n"
+ + " default: L1 L0 ICONST_0 L2 ICONST_4 L1 ICONST_M1 L3",
+ new Generator().tableSwitch(new int[] {0, 4}, true));
+ assertThrows(GeneratorException.class, () -> new Generator().tableSwitch(new int[] {1, 0}));
+ }
+
+ @Test
+ void testRet() {
+ assertEquals("RET 5", new Generator().ret(5));
+ }
+
+ @Test
+ void testReturnValue() {
+ assertEquals("RETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()V").returnValue());
+ assertEquals("IRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()Z").returnValue());
+ assertEquals("IRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()B").returnValue());
+ assertEquals("IRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()C").returnValue());
+ assertEquals("IRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()S").returnValue());
+ assertEquals("IRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()I").returnValue());
+ assertEquals("LRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()J").returnValue());
+ assertEquals("FRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()F").returnValue());
+ assertEquals("DRETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()D").returnValue());
+ assertEquals("ARETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()[I").returnValue());
+ assertEquals("ARETURN", new Generator(Opcodes.ACC_PUBLIC, "m", "()Lpkg/Class").returnValue());
+ }
+
+ @Test
+ void testGetStatic() {
+ assertEquals(
+ "GETSTATIC pkg/Class.f : I",
+ new Generator().getStatic(Type.getObjectType("pkg/Class"), "f", Type.INT_TYPE));
+ }
+
+ @Test
+ void testPutStatic() {
+ assertEquals(
+ "PUTSTATIC pkg/Class.f : I",
+ new Generator().putStatic(Type.getObjectType("pkg/Class"), "f", Type.INT_TYPE));
+ }
+
+ @Test
+ void testGetField() {
+ assertEquals(
+ "GETFIELD pkg/Class.f : I",
+ new Generator().getField(Type.getObjectType("pkg/Class"), "f", Type.INT_TYPE));
+ }
+
+ @Test
+ void testPutField() {
+ assertEquals(
+ "PUTFIELD pkg/Class.f : I",
+ new Generator().putField(Type.getObjectType("pkg/Class"), "f", Type.INT_TYPE));
+ }
+
+ @Test
+ void testInvokeVirtual() {
+ assertEquals(
+ "INVOKEVIRTUAL pkg/Class.m (I)J",
+ new Generator().invokeVirtual(Type.getObjectType("pkg/Class"), new Method("m", "(I)J")));
+ }
+
+ @Test
+ void testInvokeConstructor() {
+ assertEquals(
+ "INVOKESPECIAL pkg/Class.<init> (I)J",
+ new Generator()
+ .invokeConstructor(Type.getObjectType("pkg/Class"), new Method("<init>", "(I)J")));
+ }
+
+ @Test
+ void testInvokeStatic() {
+ assertEquals(
+ "INVOKESTATIC pkg/Class.m (I)J",
+ new Generator().invokeStatic(Type.getObjectType("pkg/Class"), new Method("m", "(I)J")));
+ }
+
+ @Test
+ void testInvokeInterface() {
+ assertEquals(
+ "INVOKEINTERFACE pkg/Class.m (I)J (itf)",
+ new Generator().invokeInterface(Type.getObjectType("pkg/Class"), new Method("m", "(I)J")));
+ }
+
+ @Test
+ void testInvokeDynamic() {
+ assertEquals(
+ "INVOKEDYNAMIC m(I)J [\n"
+ + " // handle kind 0x2 : GETSTATIC\n"
+ + " pkg/Owner.name(I)\n"
+ + " // arguments:\n"
+ + " 1, \n"
+ + " 2, \n"
+ + " 3\n"
+ + " ]",
+ new Generator()
+ .invokeDynamic(
+ "m",
+ "(I)J",
+ new Handle(Opcodes.H_GETSTATIC, "pkg/Owner", "name", "I", false),
+ 1,
+ 2,
+ 3));
+ }
+
+ @Test
+ void testNewInstance() {
+ assertEquals("NEW pkg/Class", new Generator().newInstance(Type.getObjectType("pkg/Class")));
+ }
+
+ @Test
+ void testNewArray() {
+ assertEquals("NEWARRAY T_BOOLEAN", new Generator().newArray(Type.BOOLEAN_TYPE));
+ assertEquals("NEWARRAY T_BYTE", new Generator().newArray(Type.BYTE_TYPE));
+ assertEquals("NEWARRAY T_CHAR", new Generator().newArray(Type.CHAR_TYPE));
+ assertEquals("NEWARRAY T_SHORT", new Generator().newArray(Type.SHORT_TYPE));
+ assertEquals("NEWARRAY T_INT", new Generator().newArray(Type.INT_TYPE));
+ assertEquals("NEWARRAY T_FLOAT", new Generator().newArray(Type.FLOAT_TYPE));
+ assertEquals("NEWARRAY T_LONG", new Generator().newArray(Type.LONG_TYPE));
+ assertEquals("NEWARRAY T_DOUBLE", new Generator().newArray(Type.DOUBLE_TYPE));
+ assertEquals("ANEWARRAY pkg/Class", new Generator().newArray(Type.getObjectType("pkg/Class")));
+ assertEquals("ANEWARRAY [I", new Generator().newArray(Type.getType("[I")));
+ }
+
+ @Test
+ void testArrayLength() {
+ assertEquals("ARRAYLENGTH", new Generator().arrayLength());
+ }
+
+ @Test
+ void testThrowException() {
+ assertEquals("ATHROW", new Generator().throwException());
+ assertEquals(
+ "NEW pkg/Exception DUP LDC \"msg\" "
+ + "INVOKESPECIAL pkg/Exception.<init> (Ljava/lang/String;)V ATHROW",
+ new Generator().throwException(Type.getObjectType("pkg/Exception"), "msg"));
+ }
+
+ @Test
+ void testCheckcast() {
+ assertEquals("", new Generator().checkCast(OBJECT_TYPE));
+ assertEquals("CHECKCAST pkg/Class", new Generator().checkCast(Type.getObjectType("pkg/Class")));
+ }
+
+ @Test
+ void testInstanceOf() {
+ assertEquals("INSTANCEOF pkg/Class", new Generator().instanceOf(Type.getType("Lpkg/Class;")));
+ }
+
+ @Test
+ void testMonitorEnter() {
+ assertEquals("MONITORENTER", new Generator().monitorEnter());
+ }
+
+ @Test
+ void testMonitorExit() {
+ assertEquals("MONITOREXIT", new Generator().monitorExit());
+ }
+
+ @Test
+ void testEndMethod() {
+ assertEquals("MAXSTACK = 0 MAXLOCALS = 0", new Generator().endMethod());
+ assertEquals("", new Generator(Opcodes.ACC_ABSTRACT, "m", "()V").endMethod());
+ }
+
+ @Test
+ void testCatchException() {
+ assertEquals(
+ "TRYCATCHBLOCK L0 L1 L2 null L2",
+ new Generator().catchException(new Label(), new Label(), null));
+ assertEquals(
+ "TRYCATCHBLOCK L0 L1 L2 pkg/Exception L2",
+ new Generator()
+ .catchException(new Label(), new Label(), Type.getObjectType("pkg/Exception")));
+ }
+
+ private static class GeneratorException extends Exception {
+
+ private static final long serialVersionUID = -7167830120642305483L;
+
+ public GeneratorException(final Throwable cause) {
+ super(cause);
+ }
+ }
+
+ private static class Generator implements TableSwitchGenerator {
+
+ private final Textifier textifier;
+ private final GeneratorAdapter generatorAdapter;
+
+ Generator() {
+ this(Opcodes.ACC_PUBLIC, "m", "()V");
+ }
+
+ Generator(final int access, final String name, final String descriptor) {
+ textifier = new Textifier();
+ generatorAdapter =
+ new GeneratorAdapter(
+ /* latest */ Opcodes.ASM10_EXPERIMENTAL,
+ new TraceMethodVisitor(textifier),
+ access,
+ name,
+ descriptor) {};
+ }
+
+ public String push(final boolean value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final int value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final long value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final float value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final double value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final String value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final Type value) {
+ generatorAdapter.push(value);
+ return toString();
+ }
+
+ public String push(final Handle handle) {
+ generatorAdapter.push(handle);
+ return toString();
+ }
+
+ public String loadThis() {
+ generatorAdapter.loadThis();
+ return toString();
+ }
+
+ public String loadArg(final int arg) {
+ generatorAdapter.loadArg(arg);
+ return toString();
+ }
+
+ public String loadArgs(final int arg, final int count) {
+ generatorAdapter.loadArgs(arg, count);
+ return toString();
+ }
+
+ public String loadArgs() {
+ generatorAdapter.loadArgs();
+ return toString();
+ }
+
+ public String loadArgArray() {
+ generatorAdapter.loadArgArray();
+ return toString();
+ }
+
+ public String storeArg(final int arg) {
+ generatorAdapter.storeArg(arg);
+ return toString();
+ }
+
+ public int newLocal(final Type type) {
+ return generatorAdapter.newLocal(type);
+ }
+
+ public Type getLocalType(final int local) {
+ return generatorAdapter.getLocalType(local);
+ }
+
+ public String loadLocal(final int local) {
+ generatorAdapter.loadLocal(local);
+ return toString();
+ }
+
+ public String loadLocal(final int local, final Type type) {
+ generatorAdapter.loadLocal(local, type);
+ return toString();
+ }
+
+ public String storeLocal(final int local) {
+ generatorAdapter.storeLocal(local);
+ return toString();
+ }
+
+ public String storeLocal(final int local, final Type type) {
+ generatorAdapter.storeLocal(local, type);
+ return toString();
+ }
+
+ public String arrayLoad(final Type type) {
+ generatorAdapter.arrayLoad(type);
+ return toString();
+ }
+
+ public String arrayStore(final Type type) {
+ generatorAdapter.arrayStore(type);
+ return toString();
+ }
+
+ public String pop() {
+ generatorAdapter.pop();
+ return toString();
+ }
+
+ public String pop2() {
+ generatorAdapter.pop2();
+ return toString();
+ }
+
+ public String dup() {
+ generatorAdapter.dup();
+ return toString();
+ }
+
+ public String dup2() {
+ generatorAdapter.dup2();
+ return toString();
+ }
+
+ public String dupX1() {
+ generatorAdapter.dupX1();
+ return toString();
+ }
+
+ public String dupX2() {
+ generatorAdapter.dupX2();
+ return toString();
+ }
+
+ public String dup2X1() {
+ generatorAdapter.dup2X1();
+ return toString();
+ }
+
+ public String dup2X2() {
+ generatorAdapter.dup2X2();
+ return toString();
+ }
+
+ public String swap() {
+ generatorAdapter.swap();
+ return toString();
+ }
+
+ public String swap(final Type prev, final Type type) {
+ generatorAdapter.swap(prev, type);
+ return toString();
+ }
+
+ public String math(final int op, final Type type) {
+ generatorAdapter.math(op, type);
+ return toString();
+ }
+
+ public String not() {
+ generatorAdapter.not();
+ return toString();
+ }
+
+ public String iinc(final int local, final int amount) {
+ generatorAdapter.iinc(local, amount);
+ return toString();
+ }
+
+ public String cast(final Type from, final Type to) {
+ generatorAdapter.cast(from, to);
+ return toString();
+ }
+
+ public String box(final Type type) {
+ generatorAdapter.box(type);
+ return toString();
+ }
+
+ public String valueOf(final Type type) {
+ generatorAdapter.valueOf(type);
+ return toString();
+ }
+
+ public String unbox(final Type type) {
+ generatorAdapter.unbox(type);
+ return toString();
+ }
+
+ public Label newLabel() {
+ return generatorAdapter.newLabel();
+ }
+
+ public String mark(final Label label) {
+ generatorAdapter.mark(label);
+ return toString();
+ }
+
+ public String ifCmp(final Type type, final int mode, final Label label)
+ throws GeneratorException {
+ try {
+ generatorAdapter.ifCmp(type, mode, label);
+ } catch (IllegalArgumentException e) {
+ throw new GeneratorException(e);
+ }
+ return toString();
+ }
+
+ public String ifICmp(final int mode, final Label label) throws GeneratorException {
+ try {
+ generatorAdapter.ifICmp(mode, label);
+ } catch (IllegalArgumentException e) {
+ throw new GeneratorException(e);
+ }
+ return toString();
+ }
+
+ public String ifZCmp(final int mode, final Label label) {
+ generatorAdapter.ifZCmp(mode, label);
+ return toString();
+ }
+
+ public String ifNull(final Label label) {
+ generatorAdapter.ifNull(label);
+ return toString();
+ }
+
+ public String ifNonNull(final Label label) {
+ generatorAdapter.ifNonNull(label);
+ return toString();
+ }
+
+ public String goTo(final Label label) {
+ generatorAdapter.goTo(label);
+ return toString();
+ }
+
+ public String ret(final int local) {
+ generatorAdapter.ret(local);
+ return toString();
+ }
+
+ public String tableSwitch(final int[] keys) throws GeneratorException {
+ try {
+ generatorAdapter.tableSwitch(keys, this);
+ } catch (IllegalArgumentException e) {
+ throw new GeneratorException(e);
+ }
+ return toString();
+ }
+
+ public String tableSwitch(final int[] keys, final boolean useTable) throws GeneratorException {
+ try {
+ generatorAdapter.tableSwitch(keys, this, useTable);
+ } catch (IllegalArgumentException e) {
+ throw new GeneratorException(e);
+ }
+ return toString();
+ }
+
+ @Override
+ public void generateCase(final int key, final Label end) {
+ generatorAdapter.push(key);
+ }
+
+ @Override
+ public void generateDefault() {
+ generatorAdapter.push(-1);
+ }
+
+ public String returnValue() {
+ generatorAdapter.returnValue();
+ return toString();
+ }
+
+ public String getStatic(final Type owner, final String name, final Type type) {
+ generatorAdapter.getStatic(owner, name, type);
+ return toString();
+ }
+
+ public String putStatic(final Type owner, final String name, final Type type) {
+ generatorAdapter.putStatic(owner, name, type);
+ return toString();
+ }
+
+ public String getField(final Type owner, final String name, final Type type) {
+ generatorAdapter.getField(owner, name, type);
+ return toString();
+ }
+
+ public String putField(final Type owner, final String name, final Type type) {
+ generatorAdapter.putField(owner, name, type);
+ return toString();
+ }
+
+ public String invokeVirtual(final Type owner, final Method method) {
+ generatorAdapter.invokeVirtual(owner, method);
+ return toString();
+ }
+
+ public String invokeConstructor(final Type type, final Method method) {
+ generatorAdapter.invokeConstructor(type, method);
+ return toString();
+ }
+
+ public String invokeStatic(final Type owner, final Method method) {
+ generatorAdapter.invokeStatic(owner, method);
+ return toString();
+ }
+
+ public String invokeInterface(final Type owner, final Method method) {
+ generatorAdapter.invokeInterface(owner, method);
+ return toString();
+ }
+
+ public String invokeDynamic(
+ final String name,
+ final String descriptor,
+ final Handle bootstrapMethodHandle,
+ final Object... bootstrapMethodArguments) {
+ generatorAdapter.invokeDynamic(
+ name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
+ return toString();
+ }
+
+ public String newInstance(final Type type) {
+ generatorAdapter.newInstance(type);
+ return toString();
+ }
+
+ public String newArray(final Type type) {
+ generatorAdapter.newArray(type);
+ return toString();
+ }
+
+ public String arrayLength() {
+ generatorAdapter.arrayLength();
+ return toString();
+ }
+
+ public String throwException() {
+ generatorAdapter.throwException();
+ return toString();
+ }
+
+ public String throwException(final Type type, final String msg) {
+ generatorAdapter.throwException(type, msg);
+ return toString();
+ }
+
+ public String checkCast(final Type type) {
+ generatorAdapter.checkCast(type);
+ return toString();
+ }
+
+ public String instanceOf(final Type type) {
+ generatorAdapter.instanceOf(type);
+ return toString();
+ }
+
+ public String monitorEnter() {
+ generatorAdapter.monitorEnter();
+ return toString();
+ }
+
+ public String monitorExit() {
+ generatorAdapter.monitorExit();
+ return toString();
+ }
+
+ public String endMethod() {
+ generatorAdapter.endMethod();
+ return toString();
+ }
+
+ public String catchException(final Label start, final Label end, final Type exception) {
+ generatorAdapter.catchException(start, end, exception);
+ return toString();
+ }
+
+ @Override
+ public String toString() {
+ String result =
+ textifier.text.stream()
+ .map(text -> text.toString().trim())
+ .collect(Collectors.joining(" "));
+ textifier.text.clear();
+ return result;
+ }
+ }
+}