diff --git a/src/main/java/org/eolang/jeo/representation/DataType.java b/src/main/java/org/eolang/jeo/representation/DataType.java index af8eb046d..bb9470ffc 100644 --- a/src/main/java/org/eolang/jeo/representation/DataType.java +++ b/src/main/java/org/eolang/jeo/representation/DataType.java @@ -240,6 +240,14 @@ private static byte[] hexClass(final String name) { private static DataType from(final Object data) { return Arrays.stream(DataType.values()).filter(type -> type.clazz.isInstance(data)) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unknown data type")); + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "Unknown data type of %s, class is %s", + data, + data.getClass().getName() + ) + ) + ); } } diff --git a/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethod.java b/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethod.java index 4fbedda96..e350db71b 100644 --- a/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethod.java +++ b/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethod.java @@ -24,6 +24,7 @@ package org.eolang.jeo.representation.directives; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import org.xembly.Directive; @@ -60,6 +61,13 @@ public final class DirectivesMethod implements Iterable { */ private final boolean counting; + /** + * Constructor. + */ + public DirectivesMethod() { + this("testMethod"); + } + /** * Constructor. * @param name Method name diff --git a/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitor.java b/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitor.java index 3ee3660d2..d66913204 100644 --- a/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitor.java +++ b/src/main/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitor.java @@ -23,8 +23,11 @@ */ package org.eolang.jeo.representation.directives; +import java.util.Arrays; import java.util.Iterator; +import java.util.stream.Stream; import org.eolang.jeo.representation.DefaultVersion; +import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -58,6 +61,10 @@ public final class DirectivesMethodVisitor extends MethodVisitor implements Iter */ private final DirectivesMethod method; + DirectivesMethodVisitor(final DirectivesMethod method) { + this(method, new DummyMethodVisitor()); + } + /** * Constructor. * @param method Method @@ -143,6 +150,7 @@ public void visitInvokeDynamicInsn( final Handle handler, final Object... arguments ) { + this.opcode(Opcodes.INVOKEDYNAMIC, name, descriptor, handler, arguments); super.visitInvokeDynamicInsn( name, descriptor, @@ -151,6 +159,47 @@ public void visitInvokeDynamicInsn( ); } + @Override + public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { + this.opcode(Opcodes.MULTIANEWARRAY, descriptor, numDimensions); + super.visitMultiANewArrayInsn(descriptor, numDimensions); + } + + @Override + public void visitIincInsn(final int varIndex, final int increment) { + this.opcode(Opcodes.IINC, varIndex, increment); + super.visitIincInsn(varIndex, increment); + } + + @Override + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { + this.method.opcode( + Opcodes.LOOKUPSWITCH, + Stream.concat( + Stream.of(dflt), + Stream.concat( + Arrays.stream(keys).boxed(), + Stream.of(labels) + ) + ).toArray(Object[]::new) + ); + super.visitLookupSwitchInsn(dflt, keys, labels); + } + + @Override + public void visitTableSwitchInsn( + final int min, final int max, final Label dflt, final Label... labels + ) { + this.opcode( + Opcodes.TABLESWITCH, + Stream.concat( + Stream.of(min, max, dflt), + Arrays.stream(labels) + ).toArray(Object[]::new) + ); + super.visitTableSwitchInsn(min, max, dflt, labels); + } + @Override public void visitTryCatchBlock( final Label start, @@ -175,4 +224,19 @@ public Iterator iterator() { private void opcode(final int opcode, final Object... operands) { this.method.opcode(opcode, operands); } + + /** + * Dummy method visitor. + * This method visitor does nothing. + * It is used in tests. + * @since 0.3 + */ + private static class DummyMethodVisitor extends MethodVisitor { + /** + * Constructor. + */ + DummyMethodVisitor() { + super(new DefaultVersion().api()); + } + } } diff --git a/src/test/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitorTest.java b/src/test/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitorTest.java index a239026e7..c791ce00f 100644 --- a/src/test/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitorTest.java +++ b/src/test/java/org/eolang/jeo/representation/directives/DirectivesMethodVisitorTest.java @@ -368,4 +368,70 @@ void doesNotContainTryCatchBlock() { Matchers.not(Matchers.containsString("trycatchblocks")) ); } + + @Test + void visitsMultiArrayInstructionSuccessfully() throws ImpossibleModificationException { + final DirectivesMethod method = new DirectivesMethod(); + new DirectivesMethodVisitor(method).visitMultiANewArrayInsn("java/lang/String", 2); + MatcherAssert.assertThat( + "MultiArray instruction wasn't visited successfully.", + new Xembler(method).xml(), + Matchers.allOf( + Matchers.containsString("MULTIANEWARRAY"), + Matchers.containsString("2") + ) + ); + } + + @Test + void visitsIisncInstructionSuccessfully() throws ImpossibleModificationException { + final DirectivesMethod method = new DirectivesMethod(); + new DirectivesMethodVisitor(method).visitIincInsn(1, 2); + MatcherAssert.assertThat( + "Iinc instruction wasn't visited successfully.", + new Xembler(method).xml(), + Matchers.allOf( + Matchers.containsString("IINC"), + Matchers.containsString("1"), + Matchers.containsString("2") + ) + ); + } + + @Test + void visitsLookupSwitchInstructionSuccessfully() throws ImpossibleModificationException { + final DirectivesMethod method = new DirectivesMethod(); + new DirectivesMethodVisitor(method).visitLookupSwitchInsn( + new Label(), new int[]{1, 2, 3}, new Label[]{new Label(), new Label(), new Label()} + ); + MatcherAssert.assertThat( + "LookupSwitch instruction wasn't visited successfully.", + new Xembler(method).xml(), + Matchers.allOf( + Matchers.containsString("LOOKUPSWITCH"), + Matchers.containsString("1"), + Matchers.containsString("2"), + Matchers.containsString("3"), + Matchers.containsString("label") + ) + ); + } + + @Test + void visitsTableSwitchInstructionSuccessfully() throws ImpossibleModificationException { + final DirectivesMethod method = new DirectivesMethod(); + new DirectivesMethodVisitor(method).visitTableSwitchInsn( + 1, 3, new Label(), new Label[]{new Label(), new Label(), new Label()} + ); + MatcherAssert.assertThat( + "TableSwitch instruction wasn't visited successfully.", + new Xembler(method).xml(), + Matchers.allOf( + Matchers.containsString("TABLESWITCH"), + Matchers.containsString("1"), + Matchers.containsString("3"), + Matchers.containsString("label") + ) + ); + } }