/** * Modified by @lmcgrath (https://github.com/qmx/jitescript/pull/13). */ package me.qmx.jitescript; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static me.qmx.jitescript.util.CodegenUtils.ci; import static me.qmx.jitescript.util.CodegenUtils.p; import static me.qmx.jitescript.util.CodegenUtils.sig; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import me.qmx.jitescript.JiteClassTest.DynamicClassLoader; import org.junit.Test; public class AnnotationsTest { @Test public void testAnnotationWithScalarValue() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); AnnotationData annotation = new AnnotationData(ScalarAnnotation.class); annotation.value("breakfastItem", "Waffles!"); addAnnotation(annotation); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); ScalarAnnotation annotation = clazz.getAnnotation(ScalarAnnotation.class); assertNotNull("ScalarAnnotation was not on class", annotation); assertEquals(annotation.breakfastItem(), "Waffles!"); } @Test public void testAnnotationWithArrayValue() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); AnnotationData annotation = new AnnotationData(AnnotationWithArray.class); annotation.arrayValue("favoriteColors", "pink", "purple", "green"); addAnnotation(annotation); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); AnnotationWithArray annotation = clazz.getAnnotation(AnnotationWithArray.class); assertNotNull("AnnotationWithArray was not on class", annotation); assertTrue(Arrays.equals(annotation.favoriteColors(), new String[] { "pink", "purple", "green" })); } @Test public void testAnnotationWithAnnotationValue() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); AnnotationData annotation = new AnnotationData(AnnotationWithAnnotation.class); annotation.annotationValue("element", ScalarAnnotation.class).value("breakfastItem", "Pancakes!"); addAnnotation(annotation); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); AnnotationWithAnnotation annotation = clazz.getAnnotation(AnnotationWithAnnotation.class); assertNotNull("AnnotationWithAnnotation was not on class", annotation); assertEquals(annotation.element().breakfastItem(), "Pancakes!"); } @Test public void testAnnotationWithEnumValue() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); AnnotationData annotation = new AnnotationData(AnnotationWithEnum.class); annotation.enumValue("color", Colors.PINK); addAnnotation(annotation); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); AnnotationWithEnum annotation = clazz.getAnnotation(AnnotationWithEnum.class); assertNotNull("AnnotationWithEnum was not on class", annotation); assertEquals(annotation.color(), Colors.PINK); } @Test public void testAnnotatedMethod() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); defineMethod("annotatedMethod", ACC_PUBLIC, sig(String.class), new CodeBlock() {{ ldc("Sausages!"); areturn(); annotate(ScalarAnnotation.class).value("breakfastItem", "Sausages!"); }}); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); Method method = clazz.getMethod("annotatedMethod"); ScalarAnnotation annotation = method.getAnnotation(ScalarAnnotation.class); assertNotNull("ScalarAnnotation was not on method", annotation); assertEquals(annotation.breakfastItem(), "Sausages!"); } @Test public void testAnnotatedField() throws Exception { JiteClass jiteClass = new JiteClass("AnnotatedClass", p(Object.class), new String[0]) {{ defineDefaultConstructor(); defineField("annotatedField", ACC_PUBLIC, ci(String.class), null) .addAnnotation(new AnnotationData(ScalarAnnotation.class).value("breakfastItem", "Toast!")); }}; Class<?> clazz = new DynamicClassLoader().define(jiteClass); Field field = clazz.getField("annotatedField"); ScalarAnnotation annotation = field.getAnnotation(ScalarAnnotation.class); assertNotNull("ScalarAnnotation was not on field", annotation); assertEquals(annotation.breakfastItem(), "Toast!"); } @Test public void testAnnotationsArrayValue() throws Exception { JiteClass jiteClass = new JiteClass("ClassWithRepeatedAnnotations"); jiteClass.defineDefaultConstructor(); jiteClass.annotate(Container.class).arrayValue("value", new AnnotationData(Entry.class).value("name", "Apples"), new AnnotationData(Entry.class).value("name", "Oranges") ); Class<?> clazz = new DynamicClassLoader().define(jiteClass); assertTrue(clazz.isAnnotationPresent(Container.class)); assertEquals(clazz.getAnnotationsByType(Entry.class).length, 2); assertEquals(clazz.getAnnotationsByType(Entry.class)[0].name(), "Apples"); assertEquals(clazz.getAnnotationsByType(Entry.class)[1].name(), "Oranges"); } @Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface ScalarAnnotation { String breakfastItem(); } @Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface AnnotationWithArray { String[] favoriteColors(); } @Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface AnnotationWithAnnotation { ScalarAnnotation element(); } @Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface AnnotationWithEnum { Colors color(); } @Target(TYPE) @Retention(RUNTIME) @Repeatable(Container.class) public @interface Entry { String name(); } @Target(TYPE) @Retention(RUNTIME) public @interface Container { Entry[] value(); } public enum Colors { PINK, GREEN, PURPLE } }