Skip to content

Instantly share code, notes, and snippets.

@raphw
Created June 10, 2020 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphw/d5a97cd6fc7bc66684ecea6aa7bc6e8b to your computer and use it in GitHub Desktop.
Save raphw/d5a97cd6fc7bc66684ecea6aa7bc6e8b to your computer and use it in GitHub Desktop.
Demo of type annotation errors
package foo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.concurrent.Callable;
public record SampleRecord(@RegularAnnotation @TypeAnnotation Callable<@TypeAnnotation ?>foo) {
public static void main(String[] args) throws Exception {
RecordComponent recordComponent = SampleRecord.class.getRecordComponents()[0];
assert recordComponent.getAnnotations().length == 1;
assert recordComponent.getAnnotations()[0] instanceof RegularAnnotation;
assert recordComponent.getAnnotatedType().getAnnotations()[0] instanceof TypeAnnotation;
assert ((AnnotatedParameterizedType) recordComponent.getAnnotatedType()).getAnnotatedActualTypeArguments().length == 1;
assert ((AnnotatedParameterizedType) recordComponent.getAnnotatedType()).getAnnotatedActualTypeArguments()[0].getAnnotations()[0] instanceof TypeAnnotation;
Method accessor = recordComponent.getAccessor();
assert accessor.getAnnotations().length == 1;
assert accessor.getAnnotations()[0] instanceof RegularAnnotation;
assert accessor.getAnnotatedReturnType().getAnnotations().length == 1;
assert accessor.getAnnotatedReturnType().getAnnotations()[0] instanceof TypeAnnotation;
assert ((AnnotatedParameterizedType) accessor.getAnnotatedReturnType()).getAnnotatedActualTypeArguments().length == 1;
assert ((AnnotatedParameterizedType) accessor.getAnnotatedReturnType()).getAnnotatedActualTypeArguments()[0].getAnnotations()[0] instanceof TypeAnnotation;
/*
* Errors:
* - type annotation is repurposed as a member annotation on the accessor.
* - type annotations on a type path that is not the root are lost.
*/
Constructor<?> constructor = SampleRecord.class.getConstructor(Callable.class);
assert constructor.getParameterAnnotations()[0].length == 1;
assert constructor.getParameterAnnotations()[0][0] instanceof RegularAnnotation;
assert constructor.getAnnotatedParameterTypes()[0].getAnnotations()[0] instanceof TypeAnnotation;
assert ((AnnotatedParameterizedType) constructor.getAnnotatedParameterTypes()[0]).getAnnotatedActualTypeArguments().length == 1;
assert ((AnnotatedParameterizedType) constructor.getAnnotatedParameterTypes()[0]).getAnnotatedActualTypeArguments()[0].getAnnotations()[0] instanceof TypeAnnotation;
/*
* Errors:
* - type annotations on a type path that is not the root are lost due to incorrect annotation target (FIELD)
*/
Field field = SampleRecord.class.getDeclaredField(recordComponent.getName());
assert field.getAnnotations().length == 1;
assert field.getAnnotations()[0] instanceof RegularAnnotation;
assert field.getAnnotatedType().getAnnotations()[0] instanceof TypeAnnotation;
assert ((AnnotatedParameterizedType) field.getAnnotatedType()).getAnnotatedActualTypeArguments().length == 1;
assert ((AnnotatedParameterizedType) field.getAnnotatedType()).getAnnotatedActualTypeArguments()[0].getAnnotations()[0] instanceof TypeAnnotation;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.METHOD})
@interface TypeAnnotation { }
@Retention(RetentionPolicy.RUNTIME)
@interface RegularAnnotation { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment