void use() { // this immutable type (package style used) ImIncludeTypes.builder().build(); // included on this type (package style used) ImSerializable.builder().build(); // included on package (package style used) ImTicker.builder().read(1).build(); // included in IncludeNestedTypes ImmutableIncludeNestedTypes.Retention retention = ImmutableIncludeNestedTypes.Retention.builder() .value(RetentionPolicy.CLASS) .build(); // included in IncludeNestedTypes ImmutableIncludeNestedTypes.Target target = ImmutableIncludeNestedTypes.Target.builder() .value(ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE) .build(); // package applied style "copyWith*" test // see PackageStyle retention.copyWithValue(RetentionPolicy.RUNTIME); target.copyWithValue(ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE); }
static boolean annotationMatchesTarget(Element annotationElement, ElementType elementType) { @Nullable Target target = annotationElement.getAnnotation(Target.class); if (target != null) { ElementType[] targetTypes = target.value(); if (targetTypes.length == 0) { return false; } boolean found = false; for (ElementType t : targetTypes) { if (t == elementType) { found = true; } } if (!found) { return false; } } return true; }
public List<CharSequence> getBuilderAttributeAnnotation() { if (containingType.isGenerateJacksonProperties() && protoclass().isJacksonDeserialized()) { List<CharSequence> jacksonPropertyAnnotation = Annotations.getAnnotationLines(element, Collections.singleton(Annotations.JACKSON_PROPERTY), false, ElementType.METHOD, importsResolver, nullability); List<CharSequence> annotations = Lists.newArrayList(); if (jacksonPropertyAnnotation.isEmpty()) { annotations.add(jacksonPropertyAnnotation()); } annotations.addAll(Annotations.getAnnotationLines(element, Collections.<String>emptySet(), protoclass().environment().hasJacksonLib(), ElementType.METHOD, importsResolver, nullability)); return annotations; } return ImmutableList.of(); }
private List<CharSequence> extractAnnotationsForElement(ElementType elementType, Set<String> additionalAnnotations) { List<CharSequence> allAnnotations = Lists.newArrayListWithCapacity(1); boolean dontHaveJsonPropetyAnnotationAlready = Annotations.getAnnotationLines(element, Collections.singleton(Annotations.JACKSON_PROPERTY), false, elementType, importsResolver, nullability).isEmpty(); if (dontHaveJsonPropetyAnnotationAlready) { allAnnotations.add(jacksonPropertyAnnotation()); } allAnnotations.addAll( Annotations.getAnnotationLines(element, Sets.union(additionalAnnotations, protoclass().styles().style().additionalJsonAnnotationsNames()), protoclass().environment().hasJacksonLib(), elementType, importsResolver, nullability)); return allAnnotations; }
@Test public void ttlOnPropertyLevel() throws Exception { Map<String, Object> settings = new HashMap<String, Object>(); TestHelper.configureOptionsFor( settings, Redis.class ) .associationStorage( AssociationStorageType.ASSOCIATION_DOCUMENT ) .entity( Cloud.class ) .property( "backupSnowFlakes", ElementType.METHOD ) .ttl( 1, TimeUnit.DAYS ); setupSessionFactory( settings ); createCloudWithTwoProducedAndOneBackupSnowflake(); // property-level options are applied to the type as well. // not sure, whether this is a good idea. assertThat( cloudTtl() ).isGreaterThan( TimeUnit.HOURS.toMillis( 23 ) ) .isLessThanOrEqualTo( TimeUnit.HOURS.toMillis( 24 ) ); assertThat( associationTtl() ).isGreaterThan( TimeUnit.HOURS.toMillis( 23 ) ) .isLessThanOrEqualTo( TimeUnit.HOURS.toMillis( 24 ) ); }
private JDefinedClass buildTemplateConstraint(String name) { try { JDefinedClass tplConstraint = codeModel._class(Config.CFG.getBasePackageName() + ".annot."+name, ClassType.ANNOTATION_TYPE_DECL); tplConstraint.annotate(Documented.class); tplConstraint.annotate(Retention.class).param("value", RetentionPolicy.RUNTIME); tplConstraint.annotate(Target.class).paramArray("value").param(ElementType.TYPE).param(ElementType.ANNOTATION_TYPE).param(ElementType.FIELD).param(ElementType.METHOD); // Using direct as I don't know how to build default { } with code model tplConstraint.direct("\n" + " Class<?>[] groups() default {};\n" + " String message() default \"Invalid value\";\n" + " Class<? extends Payload>[] payload() default {};\n"); // Hack to force the import of javax.validation.Payload tplConstraint.javadoc().addThrows((JClass) codeModel._ref(Payload.class)).add("Force import"); return tplConstraint; } catch (JClassAlreadyExistsException e) { throw new RuntimeException("Tried to create an already existing class: " + name, e); } }
@Test public void testGetEnumInvalid() { args.put("key", "CONSTRUCTOR"); Set<ElementType> all = EnumSet.noneOf(ElementType.class); all.add(ElementType.FIELD); all.add(ElementType.METHOD); System.out.print(all); try { ctx.getEnum("key", all); fail("IllegalArgumentException expected."); } catch (IllegalArgumentException e) { assertEquals( "Invalid parameter value 'CONSTRUCTOR' for key. Valid values are [FIELD, METHOD].", e.getMessage()); } }
/** * Inspects a class annotation. * * @param cf {@code non-null;} class file * @param ann {@code non-null;} annotation */ private void visitClassAnnotation(DirectClassFile cf, BaseAnnotations ann) { if (!args.eTypes.contains(ElementType.TYPE)) { return; } for (Annotation anAnn : ann.getAnnotations().getAnnotations()) { String annClassName = anAnn.getType().getClassType().getClassName(); if (args.aclass.equals(annClassName)) { printMatch(cf); } } }
@Test public void testConstraintViolationExceptionParameter() { final Wine bean = new Wine(); final Set<ConstraintViolation<?>> violations = new LinkedHashSet<>(); final ConstraintHelper helper = new ConstraintHelper(); final ConstraintDescriptor<NotEmpty> notEmptyNameDescriptor = new ConstraintDescriptorImpl<>(helper, (Member) null, getAnnotation("name", NotEmpty.class), ElementType.FIELD); PathImpl path = PathImpl.createPathFromString("name"); violations.add(ConstraintViolationImpl.<Wine> forParameterValidation("name-Empty", null, null, "interpolated", Wine.class, bean, new Object(), "value", path, notEmptyNameDescriptor, ElementType.PARAMETER, null, null)); path.addParameterNode("parameter1", 0); final ConstraintViolationException violationException = Mockito.mock(ConstraintViolationException.class); Mockito.when(violationException.getConstraintViolations()).thenReturn(violations); final ValidationJsonException validationJsonException = new ValidationJsonException(violationException); Assert.assertFalse(validationJsonException.getErrors().isEmpty()); Assert.assertEquals("{parameter1=[{rule=name-Empty}]}", validationJsonException.getErrors().toString()); }
public Set<ElementType> getAnnotationTargets(JvmAnnotationType annotation) { EList<JvmAnnotationReference> annotations = annotation.getAnnotations(); for (JvmAnnotationReference annoRef : annotations) { if (Target.class.getName().equals(annoRef.getAnnotation().getIdentifier())) { EList<JvmAnnotationValue> values = annoRef.getValues(); JvmAnnotationValue value = values.isEmpty() ? null : values.get(0); if (value instanceof JvmEnumAnnotationValue) { Set<ElementType> result = newHashSet(); for (JvmEnumerationLiteral elementType : ((JvmEnumAnnotationValue) value).getValues()) { final String simpleName = elementType.getSimpleName(); result.add(ElementType.valueOf(simpleName)); } return result; } } } return emptySet(); }
/** Return simple name representation of this type declaration. */ public Name toName() { String packageName = ""; if (getCompilationUnit() != null) { packageName = getCompilationUnit().getPackageName(); } List<String> simpleNames = new ArrayList<>(); TypeDeclaration current = this; while (current != null) { simpleNames.add(0, current.getName()); current = current.getEnclosingDeclaration(); } Name name = new Name(packageName, simpleNames); name.getModifiers().addAll(getModifiers()); name.setTarget(ElementType.TYPE); return name; }
/** Create new Name based on the array of Strings, with the first denoting the package name. */ public static Name of(String... names) { requireNonNull(names, "names"); if (names.length == 0) { throw new IllegalArgumentException("non-empty names array expected"); } List<String> simples = new ArrayList<>(Arrays.asList(names)); Iterator<String> iterator = simples.iterator(); String packageName = iterator.next(); iterator.remove(); if (!simples.stream().allMatch(SourceVersion::isIdentifier)) { throw new IllegalArgumentException("non-name in: " + simples); } Name name = new Name(packageName, simples); if (names.length == 1) { name.setTarget(ElementType.PACKAGE); } else if (names.length == 2) { name.setTarget(ElementType.TYPE); } return name; }
@Test void singleStaticImport() throws Exception { Member micros = TimeUnit.class.getField("MICROSECONDS"); Name parameter = Name.of("java.lang.annotation", "ElementType", "PARAMETER"); parameter.setTarget(ElementType.FIELD); parameter.setModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL); check( imports -> imports .addSingleStaticImport(Thread.State.NEW) .addSingleStaticImport(micros) .addSingleStaticImport(parameter), "import static java.lang.Thread.State.NEW;", "import static java.lang.annotation.ElementType.PARAMETER;", "import static java.util.concurrent.TimeUnit.MICROSECONDS;"); }
@Test void simple() { assertEquals("int i", MethodParameter.of(int.class, "i").list()); assertEquals("int... ia1", MethodParameter.of(int[].class, "ia1").setVariable(true).list()); assertEquals("int[]... ia2", MethodParameter.of(int[][].class, "ia2").setVariable(true).list()); MethodParameter parameter = new MethodParameter().setType(new TypeVariable()).setName("t").setFinal(true); parameter.addAnnotation(new Annotation(Name.of("", "A"))); assertEquals("final @A T t", parameter.list()); assertEquals(ElementType.PARAMETER, new MethodParameter().getAnnotationTarget()); IllegalStateException expected = expectThrows( IllegalStateException.class, () -> MethodParameter.of(int.class, "i").setVariable(true)); assertEquals(true, expected.toString().contains("array type expected")); }
@Test void testToString() { assertEquals("Name{a.b.X, target=Optional[TYPE], modifiers=[]}", of("a.b", "X").toString()); testToString(of(Object.class), "java.lang.Object", "public"); testToString(of(byte.class), "byte", "public, abstract, final"); testToString(of(Object[].class), "Object[]", "public, abstract, final"); testToString(of(Object[][].class), "Object[][]", "public, abstract, final"); testToString(of(Name.class), Name.class.getCanonicalName(), "public"); testToString(of(Character.Subset.class), "java.lang.Character.Subset", "public, static"); testToString(of(Thread.State.class), "java.lang.Thread.State", "public, static, final"); testToString( of(Thread.State.NEW), "java.lang.Thread.State.NEW", ElementType.FIELD, "public, static, final"); testToString(NormalClassDeclaration.of("Abc").toName(), "Abc", ""); testToString(CompilationUnit.of("abc").declareClass("Abc").toName(), "abc.Abc", ""); }
/** Creates the power set of the items in elements. * * This version of the method will modify the elements list * as the power set is built. * * @param <ElementType> Type of elements. * @param elements Items to create power set over. * @return Returns power set of elements. */ private static <ElementType> Set<Set<ElementType>> getPowerSetDestructive(Set<ElementType> elements) { if ( elements.isEmpty() ) { return Collections.EMPTY_SET; } else if ( elements.size() == 1 ) { HashSet<Set<ElementType>> s = new HashSet<Set<ElementType>>(); s.add(Collections.EMPTY_SET); s.add(Collections.singleton(elements.iterator().next())); return s; } else { ElementType e = elements.iterator().next(); // Next is gaurantee to work, since we check isEmpty elements.remove(e); Set<Set<ElementType>> pT = getPowerSetDestructive(elements); Set<Set<ElementType>> cross = getCrossProduct(pT, e); pT.addAll(cross); return pT; } }
@Test void rootAnnotation() { CompilationUnit unit = CompilationUnit.of("test"); Annotation annotation = Annotation.of(All.class); annotation.addObject("o", Annotation.of(Target.class, ElementType.TYPE)); annotation.addObject("p", 4711); annotation.addObject("r", Double.class); annotation.addObject("r", Float.class); NormalClassDeclaration type = unit.declareClass("Root"); type.addAnnotation(annotation); type.addTypeParameter(TypeParameter.of("X")); mark(type.declareField(TypeVariable.of("X"), "i")); Counter counter = new Counter(); Compilation.compile(null, emptyList(), asList(counter), asList(unit.toJavaFileObject())); assertEquals(1, counter.annotations.size()); assertEquals(annotation.list(), counter.annotations.get(0).list()); }
static AnnotationMetadata bindAnnotationMetadata( TurbineTyKind kind, Iterable<AnnoInfo> annotations) { if (kind != TurbineTyKind.ANNOTATION) { return null; } RetentionPolicy retention = null; ImmutableSet<ElementType> target = null; ClassSymbol repeatable = null; for (AnnoInfo annotation : annotations) { switch (annotation.sym().binaryName()) { case "java/lang/annotation/Retention": retention = bindRetention(annotation); break; case "java/lang/annotation/Target": target = bindTarget(annotation); break; case "java/lang/annotation/Repeatable": repeatable = bindRepeatable(annotation); break; default: break; } } return new AnnotationMetadata(retention, target, repeatable); }
private static ImmutableSet<ElementType> bindTarget(AnnoInfo annotation) { ImmutableSet.Builder<ElementType> result = ImmutableSet.builder(); Const val = annotation.values().get("value"); switch (val.kind()) { case ARRAY: for (Const element : ((ArrayInitValue) val).elements()) { if (element.kind() == Kind.ENUM_CONSTANT) { bindTargetElement(result, (EnumConstantValue) element); } } break; case ENUM_CONSTANT: bindTargetElement(result, (EnumConstantValue) val); break; default: break; } return result.build(); }
private static MethodInfo bindMethod(Env<ClassSymbol, TypeBoundClass> env, MethodInfo base) { ImmutableList.Builder<AnnoInfo> declarationAnnotations = ImmutableList.builder(); Type returnType = disambiguate( env, base.name().equals("<init>") ? ElementType.CONSTRUCTOR : ElementType.METHOD, base.returnType(), base.annotations(), declarationAnnotations); return new MethodInfo( base.sym(), base.tyParams(), returnType, bindParameters(env, base.parameters()), base.exceptions(), base.access(), base.defaultValue(), base.decl(), declarationAnnotations.build(), base.receiver() != null ? bindParam(env, base.receiver()) : null); }
/** * Moves type annotations in {@code annotations} to {@code type}, and adds any declaration * annotations on {@code type} to {@code declarationAnnotations}. */ private static Type disambiguate( Env<ClassSymbol, TypeBoundClass> env, ElementType declarationTarget, Type type, ImmutableList<AnnoInfo> annotations, Builder<AnnoInfo> declarationAnnotations) { // desugar @Repeatable annotations before disambiguating: annotation containers may target // a subset of the types targeted by their element annotation annotations = groupRepeated(env, annotations); ImmutableList.Builder<AnnoInfo> typeAnnotations = ImmutableList.builder(); for (AnnoInfo anno : annotations) { Set<ElementType> target = env.get(anno.sym()).annotationMetadata().target(); if (target.contains(ElementType.TYPE_USE)) { typeAnnotations.add(anno); } if (target.contains(declarationTarget)) { declarationAnnotations.add(anno); } } return addAnnotationsToType(type, typeAnnotations.build()); }
@Override public AnnotationMetadata get() { if ((access() & TurbineFlag.ACC_ANNOTATION) != TurbineFlag.ACC_ANNOTATION) { return null; } RetentionPolicy retention = null; ImmutableSet<ElementType> target = null; ClassSymbol repeatable = null; for (ClassFile.AnnotationInfo annotation : classFile.get().annotations()) { switch (annotation.typeName()) { case "Ljava/lang/annotation/Retention;": retention = bindRetention(annotation); break; case "Ljava/lang/annotation/Target;": target = bindTarget(annotation); break; case "Ljava/lang/annotation/Repeatable;": repeatable = bindRepeatable(annotation); break; default: break; } } return new AnnotationMetadata(retention, target, repeatable); }
private static ImmutableSet<ElementType> bindTarget(AnnotationInfo annotation) { ImmutableSet.Builder<ElementType> result = ImmutableSet.builder(); ElementValue val = annotation.elementValuePairs().get("value"); switch (val.kind()) { case ARRAY: for (ElementValue element : ((ArrayValue) val).elements()) { if (element.kind() == Kind.ENUM) { bindTargetElement(result, (EnumConstValue) element); } } break; case ENUM: bindTargetElement(result, (EnumConstValue) val); break; default: break; } return result.build(); }
public void compileAnnotations (AttrContainer container, ElementType etype) { if (container == null) return; int n = numAnnotations(); for (int i = 0; i < n; i++) { Object ann = getAnnotation(i).valueIfConstant(); if (ann != null) { AnnotationEntry ae = (AnnotationEntry) Proxy.getInvocationHandler(ann); if (container != null && ae.hasTarget(etype)) RuntimeAnnotationsAttr.maybeAddAnnotation(container, ae); } } }
public TypeModel(Type type, Modifier[] modifiers, VariableModel extendsType, Set<VariableModel> interfaces, List<GenericVariableModel> genericVariables, List<AnnotationModel> annotations, Map<String, FieldModel> fields, Map<String, MethodModel> methods, InclusionType inclusion, List<String> values, Map<String, Object[]> valuesWithFields, List<String> fieldOrder, SubTypeModel subTypes, RetentionPolicy retention, ElementType[] elementTypes, List<String> customConstructorFields) { this.type = type; this.modifiers = modifiers; this.extendsType = extendsType; this.interfaces = interfaces; this.genericVariables = genericVariables; this.annotations = annotations; this.fields = fields; this.methods = methods; this.inclusion = inclusion; this.values = values; this.valuesWithFields = valuesWithFields; this.fieldOrder = fieldOrder; this.subTypes = subTypes; this.retention = retention; this.elementTypes = elementTypes; this.customConstructorFields = customConstructorFields; }
@Test public void loadAndCheckAnnotatedAnnotation() throws Exception { ClassInfo classInfo = ClassInfo.newAnnotation() .name("org.kordamp.naum.processor.klass.AnnotatedAnnotation") .iface(Annotation.class.getName()) .build(); classInfo.addToAnnotations(annotationInfo() .name(Retention.class.getName()) .annotationValue("value", new EnumValue(RetentionPolicy.class.getName(), "SOURCE")) .build()); classInfo.addToAnnotations(annotationInfo() .name(Target.class.getName()) .annotationValue("value", newArrayValue(asList( newEnumValue(ElementType.class.getName(), ElementType.TYPE.name()), newEnumValue(ElementType.class.getName(), ElementType.FIELD.name())) )) .build()); loadAndCheck("org/kordamp/naum/processor/klass/AnnotatedAnnotation.class", (klass) -> { assertThat(klass.getContentHash(), equalTo(classInfo.getContentHash())); assertThat(klass, equalTo(classInfo)); }); }
/** * Note that: * * <pre> * If no annotation matches the specified parameter, the property will be ignored. * </pre> * * @param key * @param expectedType * @return the configured value */ private <U> U lookup(String key, Class<U> expectedType) { Config config = getConfig(); Optional<U> value = null; if (ElementType.METHOD.equals(annotationSource)) { // <classname>/<methodname>/<annotation>/<parameter> value = config.getOptionalValue(getConfigKeyForMethod() + key, expectedType); } else { // <classname>/<annotation>/<parameter> value = config.getOptionalValue(getConfigKeyForClass() + key, expectedType); } if (!value.isPresent()) { // <annotation>/<parameter> value = config.getOptionalValue(getConfigType().getSimpleName() + "/" + key, expectedType); } // annotation values return value.isPresent() ? value.get() : getConfigFromAnnotation(key); }
static List<CharSequence> getAnnotationLines( Element element, Set<String> includeAnnotations, boolean includeJacksonAnnotations, ElementType elementType, Function<String, String> importsResolver, @Nullable NullabilityAnnotationInfo nullability) { return getAnnotationLines(element, includeAnnotations, false, includeJacksonAnnotations, elementType, importsResolver, nullability); }
static List<CharSequence> getAnnotationLines( Element element, Set<String> includeAnnotations, boolean includeAllAnnotations, boolean includeJacksonAnnotations, ElementType elementType, Function<String, String> importsResolver, @Nullable NullabilityAnnotationInfo nullability) { List<CharSequence> lines = Lists.newArrayList(); Set<String> seenAnnotations = new HashSet<>(); for (AnnotationMirror annotation : element.getAnnotationMirrors()) { TypeElement annotationElement = (TypeElement) annotation.getAnnotationType().asElement(); if (annotationTypeMatches(element, annotationElement, includeAnnotations, includeAllAnnotations, includeJacksonAnnotations, seenAnnotations, lines, importsResolver, elementType, nullability) && annotationMatchesTarget(annotationElement, elementType)) { lines.add(AnnotationMirrors.toCharSequence(annotation, importsResolver)); } } return lines; }
public List<CharSequence> getBuilderAnnotations() { Optional<DeclaringType> declaringType = constitution.protoclass().declaringType(); if (declaringType.isPresent() && declaringType.get().jacksonSerializeMode() == JacksonMode.BUILDER) { return Annotations.getAnnotationLines( element, Collections.<String>emptySet(), true, ElementType.TYPE, newTypeStringResolver(), null); } return ImmutableList.of(); }
public List<CharSequence> passedAnnotations() { return Annotations.getAnnotationLines( element, Sets.union( constitution.style().passAnnotationsNames(), constitution.style().additionalJsonAnnotationsNames()), false, ElementType.TYPE, newTypeStringResolver(), null); }
public List<CharSequence> getAnnotations() { if (containingType.isGenerateJacksonProperties()) { return extractAnnotationsForElement( ElementType.METHOD, protoclass().styles().style().passAnnotationsNames()); } return Annotations.getAnnotationLines(element, protoclass().styles().style().passAnnotationsNames(), false, ElementType.METHOD, importsResolver, nullability); }
public List<CharSequence> getFieldAnnotations() { return Annotations.getAnnotationLines(element, protoclass().styles().style().passAnnotationsNames(), false, ElementType.FIELD, importsResolver, null/* do not propagate nullable here */); }
public CharSequence getConstructorParameterAnnotations() { List<CharSequence> annotations = Annotations.getAnnotationLines(element, protoclass().styles().style().passAnnotationsNames(), false, ElementType.PARAMETER, importsResolver, nullability); if (!annotations.isEmpty()) { return Joiner.on(' ').join(annotations).concat(" "); } return ""; }
@Value.Lazy String asLocalPrefix() { boolean applicableToLocal = Annotations.annotationMatchesTarget( element(), ElementType.LOCAL_VARIABLE); return applicableToLocal ? asPrefix() : ""; }
@Test public void testGetEnumOptionalInvalid() { args.put("key", "CONSTRUCTOR"); Set<ElementType> all = EnumSet.noneOf(ElementType.class); all.add(ElementType.FIELD); all.add(ElementType.METHOD); assertEquals(null, ctx.getEnumOptional("key", all)); }