/** * Returns the annotation value for the default value method of the given annotation type on the given element or null if not found. */ @Pure public static @Nullable AnnotationValue getAnnotationValue(@Nonnull Element element, @Nonnull Class<? extends Annotation> annotationType) { return getAnnotationValue(element, annotationType, "value"); }
protected FieldInformationImplementation(@Nonnull Element element, @Nonnull TypeMirror type, @Nonnull DeclaredType containingType) { super(element, type, containingType); this.defaultValue = ProcessingUtility.getString(ProcessingUtility.getAnnotationValue(element, Default.class)); }
/** * Returns the annotation value for the given method name of the given annotation type on the given element or null if not found. */ @Pure public static @Nullable AnnotationValue getAnnotationValue(@Nonnull Element element, @Nonnull Class<? extends Annotation> annotationType, @Nonnull String methodName) { final @Nullable AnnotationMirror annotationMirror = getAnnotationMirror(element, annotationType); return annotationMirror != null ? getAnnotationValue(annotationMirror, methodName) : null; }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nullable AnnotationValue condition = ProcessingUtility.getAnnotationValue(annotationMirror, "condition"); final @Nullable AnnotationValue message = ProcessingUtility.getAnnotationValue(annotationMirror, "message"); if (element.getKind() == ElementKind.METHOD && ((ExecutableElement) element).getReturnType().getKind() == TypeKind.VOID) { return Contract.with(String.valueOf(condition != null ? condition.getValue() : null), String.valueOf(message != null ? message.getValue() : null)); } else { return Contract.with(String.valueOf(condition != null ? condition.getValue() : null), String.valueOf(message != null ? message.getValue() : null), element); } }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nullable AnnotationValue condition = ProcessingUtility.getAnnotationValue(annotationMirror, "condition"); final @Nullable AnnotationValue message = ProcessingUtility.getAnnotationValue(annotationMirror, "message"); return Contract.with(String.valueOf(condition != null ? condition.getValue() : null), String.valueOf(message != null ? message.getValue() : null)); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nullable AnnotationValue condition = ProcessingUtility.getAnnotationValue(annotationMirror, "condition"); final @Nullable AnnotationValue message = ProcessingUtility.getAnnotationValue(annotationMirror, "message"); return Contract.with(String.valueOf(condition != null ? condition.getValue() : null), String.valueOf(message != null ? message.getValue() : null), element); }
/** * Returns an object that wraps the given {@link #getCondition() condition} and {@link #getMessage() message} with the element name as {@link #getArguments() argument}. * Each number sign in the condition and the message is replaced with the {@link ValueAnnotationValidator#getName(javax.lang.model.element.Element) name} of the element. * Each at sign in the condition and the message is replaced with the {@link AnnotationValue#getValue() value} of the given annotation mirror. */ @Pure public static @Nonnull Contract with(@Nonnull String condition, @Nonnull String message, @Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @Nonnull String suffix) { final @Nonnull String name = ValueAnnotationValidator.getName(element); final @Nullable AnnotationValue annotationValue = ProcessingUtility.getAnnotationValue(annotationMirror); final @Nullable Object object = annotationValue != null ? annotationValue.getValue() : null; final @Nonnull String value = String.valueOf(object) + (object instanceof Long ? "l" : ""); return new Contract(condition.replace("#", name).replace("@", value), message.replace("#", Strings.decamelize(name)).replace("@", value), name + (suffix.isEmpty() ? "" : " == null ? null : " + name + suffix)); }
/** * Returns the annotation value for the value method of the given annotation mirror or null if not found. */ @Pure @LogsErrorWhenReturningNull public static @Nullable AnnotationValue getAnnotationValue(@Nonnull AnnotationMirror annotationMirror) { return getAnnotationValue(annotationMirror, "value"); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nonnull StringBuilder condition = new StringBuilder("# == null"); for (@Nonnull ElementKind kind : ProcessingUtility.getEnums(ProcessingUtility.getAnnotationValue(annotationMirror), ElementKind.class)) { condition.append(" || ").append(ElementKindValidator.getCondition(element, kind, typeImporter)); } return Contract.with(condition.toString(), "The # has to be null or one of the specified kinds but was $.", element); }
/** * Returns the value of the given annotation mirror as a suffix for the method name. */ @Pure protected static @Nonnull String getSuffix(@Nonnull AnnotationMirror annotationMirror) { // The following line is only necessary because the IncorrectUsage testing annotation passes its own annotation mirror. if (ProcessingUtility.getSimpleName(annotationMirror).equals("IncorrectUsage")) { return ""; } final @Nullable AnnotationValue annotationValue = ProcessingUtility.getAnnotationValue(annotationMirror); final @Nullable String string = ProcessingUtility.getString(annotationValue); return string == null ? "" : Strings.uppercaseFirstCharacter(string); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nonnull StringBuilder condition = new StringBuilder("# == null"); for (@Nonnull NestingKind kind : ProcessingUtility.getEnums(ProcessingUtility.getAnnotationValue(annotationMirror), NestingKind.class)) { condition.append(" || ").append(NestingKindValidator.getCondition(element, kind, typeImporter)); } return Contract.with(condition.toString(), "The # has to be null or have one of the specified nesting kinds but was $.", element); }
/** * Returns true if the field is annotated with @MaxSize and the value is lower or equal than the given max size parameter value. */ @Pure public boolean hasMaxSize(int maxSize) { boolean hasMaxSize = true; final @Nullable AnnotationMirror first = annotationMirrors.findFirst(annotationMirror -> ProcessingUtility.getQualifiedName(annotationMirror).equals(MaxSize.class.getName())); hasMaxSize = hasMaxSize && first != null; if (first != null) { final @Nullable AnnotationValue annotationValue = ProcessingUtility.getAnnotationValue(first); Require.that(annotationValue != null).orThrow("MaxSize requires an annotation value."); hasMaxSize = hasMaxSize && ((int) annotationValue.getValue()) <= maxSize; } return hasMaxSize; }
/** * Returns the annotation handlers of the given type which are found with the given meta-annotation type on the annotations of the given element. */ @Pure @SuppressWarnings("unchecked") public static @Capturable <H extends AnnotationHandler> @Modifiable @Nonnull Map<@Nonnull AnnotationMirror, @Nonnull H> getAnnotationHandlers(@Nonnull Element element, @Nonnull Class<? extends Annotation> metaAnnotationType, @Nonnull Class<H> annotationHandlerType) { final @Nonnull Map<@Nonnull AnnotationMirror, @Nonnull H> result = new LinkedHashMap<>(); for (@Nonnull AnnotationMirror annotationMirror : ProcessingUtility.getAnnotationMirrors(element)) { final @Nullable H annotationHandler; final @Nonnull String cacheKey = ProcessingUtility.getQualifiedName(annotationMirror) + "$" + metaAnnotationType.getCanonicalName(); if (cachedAnnotationHandlers.containsKey(cacheKey)) { final @Nullable AnnotationHandler cachedAnnotationHandler = cachedAnnotationHandlers.get(cacheKey); annotationHandler = annotationHandlerType.isInstance(cachedAnnotationHandler) ? (H) cachedAnnotationHandler : null; } else { final @Nonnull TypeElement annotationElement = (TypeElement) annotationMirror.getAnnotationType().asElement(); final @Nullable AnnotationValue metaAnnotationValue = ProcessingUtility.getAnnotationValue(annotationElement, metaAnnotationType); annotationHandler = ProcessingUtility.getInstance(metaAnnotationValue, annotationHandlerType); cachedAnnotationHandlers.put(cacheKey, annotationHandler); } if (annotationHandler != null) { ProcessingLog.debugging("Found the annotation handler $ for", SourcePosition.of(element, annotationMirror), annotationHandler.getClass().getCanonicalName()); annotationHandler.checkUsage(element, annotationMirror, ErrorLogger.INSTANCE); result.put(annotationMirror, annotationHandler); } } return result; }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nonnull TypeMirror declaredType = ProcessingUtility.getType(element); final @Nullable Class<?> desiredType = ProcessingUtility.getClass(ProcessingUtility.getAnnotationValue(annotationMirror)); if (desiredType != null && !ProcessingUtility.isRawSubtype(declaredType, desiredType)) { errorLogger.log("The type $ is not a subtype of $:", SourcePosition.of(element), ProcessingUtility.getSimpleName(declaredType), desiredType.getSimpleName()); } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nonnull TypeMirror declaredType = ProcessingUtility.getType(element); final @Nullable Class<?> desiredType = ProcessingUtility.getClass(ProcessingUtility.getAnnotationValue(annotationMirror)); if (desiredType != null && ProcessingUtility.isRawlyAssignable(declaredType, desiredType)) { errorLogger.log("The value of type $ is rawly assignable to $:", SourcePosition.of(element), ProcessingUtility.getSimpleName(declaredType), desiredType.getSimpleName()); } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { super.checkUsage(element, annotationMirror, errorLogger); final @Nullable String regex = ProcessingUtility.getString(ProcessingUtility.getAnnotationValue(annotationMirror)); if (regex != null) { try { Pattern.compile(regex); } catch (@Nonnull PatternSyntaxException exception) { errorLogger.log("The regular expression $ is invalid because of: " + exception.getDescription(), SourcePosition.of(element, annotationMirror), regex); } } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nonnull TypeMirror declaredType = ProcessingUtility.getType(element); final @Nullable Class<?> desiredType = ProcessingUtility.getClass(ProcessingUtility.getAnnotationValue(annotationMirror)); if (desiredType != null && !ProcessingUtility.isRawlyAssignable(declaredType, desiredType)) { errorLogger.log("The value of type $ is not rawly assignable to $:", SourcePosition.of(element), ProcessingUtility.getSimpleName(declaredType), desiredType.getSimpleName()); } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nonnull TypeMirror declaredType = ProcessingUtility.getType(element); final @Nullable Class<?> desiredType = ProcessingUtility.getClass(ProcessingUtility.getAnnotationValue(annotationMirror)); if (desiredType != null && ProcessingUtility.isRawSubtype(declaredType, desiredType)) { errorLogger.log("The type $ is a subtype of $:", SourcePosition.of(element), ProcessingUtility.getSimpleName(declaredType), desiredType.getSimpleName()); } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nullable AnnotationHandler annotationHandler = ProcessingUtility.getInstance(ProcessingUtility.getAnnotationValue(annotationMirror), AnnotationHandler.class); if (annotationHandler != null) { final @Nonnull Logger logger = new Logger(); annotationHandler.checkUsage(element, annotationMirror, logger); if (logger.isCorrectlyUsed()) { errorLogger.log("The annotation $ is used correctly:", SourcePosition.of(element, annotationMirror), annotationHandler.getAnnotationNameWithLeadingAt()); } } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { ValueAnnotationValidator.super.checkUsage(element, annotationMirror, errorLogger); if (ProcessingUtility.isRawSubtype(element, Class.class) && !typeKinds.containsAll(ProcessingUtility.getEnums(ProcessingUtility.getAnnotationValue(annotationMirror), ElementKind.class))) { errorLogger.log("In case of classes, the annotation '@TypeKind' may only be used with CLASS, INTERFACE, ENUM and ANNOTATION_TYPE:", SourcePosition.of(element, annotationMirror)); } }