private void configureAnnotationFromDefinition(AnnotationNode definition, AnnotationNode root) { ClassNode type = definition.getClassNode(); if (!type.isResolved()) return; Class clazz = type.getTypeClass(); if (clazz == Retention.class) { Expression exp = definition.getMember("value"); if (!(exp instanceof PropertyExpression)) return; PropertyExpression pe = (PropertyExpression) exp; String name = pe.getPropertyAsString(); RetentionPolicy policy = RetentionPolicy.valueOf(name); setRetentionPolicy(policy, root); } else if (clazz == Target.class) { Expression exp = definition.getMember("value"); if (!(exp instanceof ListExpression)) return; ListExpression le = (ListExpression) exp; int bitmap = 0; for (Expression e : le.getExpressions()) { PropertyExpression element = (PropertyExpression) e; String name = element.getPropertyAsString(); ElementType value = ElementType.valueOf(name); bitmap |= getElementCode(value); } root.setAllowedTargets(bitmap); } }
@Test(dataProvider = "retentionPolicyTestCase") public void annotationTest(RetentionPolicy policy) { assertEval("import java.lang.annotation.*;"); String annotationSource = "@Retention(RetentionPolicy." + policy.toString() + ")\n" + "@interface A {}"; assertEval(annotationSource); String classSource = "@A class C {\n" + " @A C() {}\n" + " @A void f() {}\n" + " @A int f;\n" + " @A class Inner {}\n" + "}"; assertEval(classSource); String isRuntimeVisible = policy == RetentionPolicy.RUNTIME ? "true" : "false"; assertEval("C.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible); assertEval( "C.class.getDeclaredConstructor().getAnnotationsByType(A.class).length > 0;", isRuntimeVisible); assertEval( "C.class.getDeclaredMethod(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible); assertEval( "C.class.getDeclaredField(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible); assertEval("C.Inner.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible); }
public static void configureAnnotationFromDefinition( AnnotationNode definition, AnnotationNode root) { ClassNode type = definition.getClassNode(); if ("java.lang.annotation.Retention".equals(type.getName())) { Expression exp = definition.getMember("value"); if (!(exp instanceof PropertyExpression)) return; PropertyExpression pe = (PropertyExpression) exp; String name = pe.getPropertyAsString(); RetentionPolicy policy = RetentionPolicy.valueOf(name); setRetentionPolicy(policy, root); } else if ("java.lang.annotation.Target".equals(type.getName())) { Expression exp = definition.getMember("value"); if (!(exp instanceof ListExpression)) return; ListExpression le = (ListExpression) exp; int bitmap = 0; for (Expression e : le.getExpressions()) { if (!(e instanceof PropertyExpression)) return; PropertyExpression element = (PropertyExpression) e; String name = element.getPropertyAsString(); ElementType value = ElementType.valueOf(name); bitmap |= getElementCode(value); } root.setAllowedTargets(bitmap); } }
@Nullable private static String doCheckRepeatableAnnotation(@NotNull PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if (!(owner instanceof PsiModifierList)) return null; PsiElement target = ((PsiModifierList) owner).getParent(); if (!(target instanceof PsiClass) || !((PsiClass) target).isAnnotationType()) return null; PsiClass container = getRepeatableContainer(annotation); if (container == null) return null; PsiMethod[] methods = container.findMethodsByName("value", false); if (methods.length == 0) { return JavaErrorMessages.message( "annotation.container.no.value", container.getQualifiedName()); } if (methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass) target, PsiSubstitutor.EMPTY).createArrayType(); if (!expected.equals(methods[0].getReturnType())) { return JavaErrorMessages.message( "annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected)); } } RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass) target); if (targetPolicy != null) { RetentionPolicy containerPolicy = getRetentionPolicy(container); if (containerPolicy != null && targetPolicy.compareTo(containerPolicy) > 0) { return JavaErrorMessages.message( "annotation.container.low.retention", container.getQualifiedName(), containerPolicy); } } Set<PsiAnnotation.TargetType> repeatableTargets = PsiImplUtil.getAnnotationTargets((PsiClass) target); if (repeatableTargets != null) { Set<PsiAnnotation.TargetType> containerTargets = PsiImplUtil.getAnnotationTargets(container); if (containerTargets != null && !repeatableTargets.containsAll(containerTargets)) { return JavaErrorMessages.message( "annotation.container.wide.target", container.getQualifiedName()); } } return null; }
@DataProvider(name = "retentionPolicyTestCase") public Object[][] retentionPolicyTestCaseGenerator() { List<Object[]> list = new ArrayList<>(); for (RetentionPolicy policy : RetentionPolicy.values()) { list.add(new Object[] {policy}); } return list.toArray(new Object[list.size()][]); }
private void configureAnnotation(AnnotationNode node, Annotation annotation) { Class type = annotation.annotationType(); if (type == Retention.class) { Retention r = (Retention) annotation; RetentionPolicy value = r.value(); setRetentionPolicy(value, node); node.setMember( "value", new PropertyExpression( new ClassExpression(ClassHelper.makeWithoutCaching(RetentionPolicy.class, false)), value.toString())); } else if (type == Target.class) { Target t = (Target) annotation; ElementType[] elements = t.value(); ListExpression elementExprs = new ListExpression(); for (ElementType element : elements) { elementExprs.addExpression( new PropertyExpression( new ClassExpression(ClassHelper.ELEMENT_TYPE_TYPE), element.name())); } node.setMember("value", elementExprs); } else { Method[] declaredMethods; try { declaredMethods = type.getDeclaredMethods(); } catch (SecurityException se) { declaredMethods = new Method[0]; } for (Method declaredMethod : declaredMethods) { try { Object value = declaredMethod.invoke(annotation); Expression valueExpression = annotationValueToExpression(value); if (valueExpression == null) continue; node.setMember(declaredMethod.getName(), valueExpression); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } } }
@Nullable private static RetentionPolicy getRetentionPolicy(PsiClass annotation) { PsiModifierList modifierList = annotation.getModifierList(); if (modifierList != null) { PsiAnnotation retentionAnno = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION); if (retentionAnno == null) return RetentionPolicy.CLASS; PsiAnnotationMemberValue policyRef = PsiImplUtil.findAttributeValue(retentionAnno, null); if (policyRef instanceof PsiReference) { PsiElement field = ((PsiReference) policyRef).resolve(); if (field instanceof PsiEnumConstant) { String name = ((PsiEnumConstant) field).getName(); try { return RetentionPolicy.valueOf(name); } catch (Exception e) { LOG.warn("Unknown policy: " + name); } } } } return null; }
public void visitEnum(String name, String desc, String value) { myRetentionPolicy = RetentionPolicy.valueOf(value); }