/** * Returns the type of the given element or the return type if the given element is an executable element. */ @Pure public static @Nonnull TypeMirror getType(@Nonnull Element element) { return getType(element.asType()); }
/** * Returns whether the type of the given element corresponds to the given type. */ @Pure public static boolean correspond(@Nonnull Element element, @Nonnull Class<?> type) { return correspond(getType(element), type); }
/** * Returns whether the given element is rawly assignable to the given type. */ @Pure public static boolean isRawlyAssignable(@Nonnull Element element, @Nonnull Class<?> type) { return isRawlyAssignable(getType(element), type); }
/** * Returns whether the type of the given element is a raw subtype of the given type. */ @Pure public static boolean isRawSubtype(@Nonnull Element element, @Nonnull Class<?> type) { return isRawSubtype(getType(element), type); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { final @Nonnull String suffix = getSuffix(annotationMirror); final @Nonnull TypeMirror elementType = ProcessingUtility.getType(element); final @Nonnull Element enclosingElement = element.getEnclosingElement(); final boolean primitive = elementType.getKind().isPrimitive() || element.getAnnotation(Nonnull.class) == null && element.getAnnotation(Nullable.class) == null; final boolean local = hasMethodToCheckValidity((DeclaredType) ProcessingUtility.getSurroundingType(element).asType(), elementType, enclosingElement.getKind() == ElementKind.CONSTRUCTOR, suffix); return Contract.with((primitive ? "" : "# == null || ") + (local ? "" : ((ExecutableElement) enclosingElement).getParameters().get(0).getSimpleName() + ".") + "isValid" + suffix + "(#)", "The # has to be " + (primitive ? "" : "null or ") + "valid but was $.", element); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { return Contract.with((ProcessingUtility.getType(element).getKind().isPrimitive() ? "" : "# == null || ") + "String.valueOf(#).equals(\"@\")", "The # has to equal '@' but was $.", element, annotationMirror); }
@Pure @Override public @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { return Contract.with((ProcessingUtility.getType(element).getKind().isPrimitive() ? "" : "# == null || ") + "!String.valueOf(#).equals(\"@\")", "The # may not equal '@' but was $.", element, annotationMirror); }
/** * Returns the boxed type of the given type mirror or its component type in case of arrays. */ @Pure public static @Nonnull TypeMirror getBoxedType(@Nonnull TypeMirror typeMirror) { if (isPrimitive(typeMirror)) { return getType(StaticProcessingEnvironment.getTypeUtils().boxedClass((PrimitiveType) typeMirror)); } else { return typeMirror; } }
/** * Returns the component type of the type of the given element if it is an array or an iterable and logs errors with the given logger otherwise. */ @Pure @LogsErrorWhenReturningNull public static @Nullable TypeMirror getComponentType(@Nonnull Element element, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { return getComponentType(getType(element), errorLogger); }
/** * Returns the component types of the type of the given element if it is an array or an iterable and logs errors with the given logger otherwise. */ @Pure @LogsErrorWhenReturningNull public static @Nullable List<TypeMirror> getComponentTypes(@Nonnull Element element, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { return getComponentTypes(getType(element), errorLogger); }
@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 String suffix = getSuffix(annotationMirror); final @Nonnull TypeMirror elementType = ProcessingUtility.getType(element); final @Nonnull Element enclosingElement = element.getEnclosingElement(); final boolean inConstructor = enclosingElement.getKind() == ElementKind.CONSTRUCTOR; if (hasMethodToCheckValidity((DeclaredType) ProcessingUtility.getSurroundingType(element).asType(), elementType, inConstructor, suffix)) { return; } if (enclosingElement.getKind() == ElementKind.METHOD) { @Nonnull TypeMirror typeOfFirstParameter = ((ExecutableElement) enclosingElement).getParameters().get(0).asType(); if (typeOfFirstParameter.getKind() == TypeKind.TYPEVAR) { typeOfFirstParameter = ((TypeVariable) typeOfFirstParameter).getUpperBound(); } if (typeOfFirstParameter.getKind() == TypeKind.DECLARED && hasMethodToCheckValidity((DeclaredType) typeOfFirstParameter, elementType, false, suffix)) { return; } } final @Nonnull String annotationValue = suffix.isEmpty() ? "" : Brackets.inRound(Quotes.inDouble(suffix)); if (inConstructor) { errorLogger.log("The annotation '@Valid" + annotationValue + "' may only be used on constructor parameters of types that have a 'public static boolean isValid" + suffix + "(value)' method for the corresponding type.", SourcePosition.of(element, annotationMirror)); } else { errorLogger.log("The annotation '@Valid" + annotationValue + "' may only be used in types that have a corresponding non-private '(static) boolean isValid" + suffix + "(value)' method or on method parameters where the first method parameter has such a method.", SourcePosition.of(element, annotationMirror)); } }
@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 @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 @Nonnull Contract generateContract(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull TypeImporter typeImporter) { if (ProcessingUtility.isRawSubtype(element, CharSequence.class)) { return generateContract("# == null || #.length() " + getSizeComparison(), "The length of the # has to be " + getMessageCondition() + " but was $.", element, annotationMirror, ".length()"); } else if (ProcessingUtility.getType(element).getKind() == TypeKind.ARRAY) { return generateContract("# == null || #.length " + getSizeComparison(), "The length of the # has to be " + getMessageCondition() + " but was $.", element, annotationMirror, ".length"); } else { return generateContract("# == null || #.size() " + getSizeComparison(), "The size of the # has to be " + getMessageCondition() + " but was $.", element, annotationMirror, ".size()"); } }