@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { if (element.getKind() == ElementKind.PARAMETER) { final @Nonnull Element enclosingElement = element.getEnclosingElement(); if (!(enclosingElement.getKind() == ElementKind.CONSTRUCTOR && ProcessingUtility.getConstructors(ProcessingUtility.getSurroundingType(element)).isSingle() || ProcessingUtility.hasAnnotation(enclosingElement, Recover.class))) { errorLogger.log("The generation annotation may only be used on parameters of a unique constructor or an executable annotated with '@Recover'.", SourcePosition.of(element, annotationMirror)); } } else if (element.getKind() == ElementKind.METHOD) { final @Nonnull ExecutableElement method = (ExecutableElement) element; if (!method.getModifiers().contains(Modifier.ABSTRACT)/* || !ProcessingUtility.isGetter(method)*/) { // TODO: @Default also has to be allowed on generated properties. errorLogger.log("The generation annotation may only be used on abstract getters.", SourcePosition.of(element, annotationMirror)); } } else { errorLogger.log("The generation annotation may only be used on parameters and methods.", SourcePosition.of(element, annotationMirror)); } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { for (@Nonnull ExecutableElement method : ProcessingUtility.getAllMethods((TypeElement) element).filter(ProcessingUtility::isDeclaredInDigitalIDLibrary).filterNot(method -> method.getModifiers().contains(Modifier.STATIC))) { if (!ProcessingUtility.hasAnnotation(method, Pure.class) && !ProcessingUtility.hasAnnotation(method, PureWithSideEffects.class)) { errorLogger.log("The read-only type $ may only contain pure non-static methods.", SourcePosition.of(method), element); } } for (@Nonnull VariableElement field : ProcessingUtility.getAllFields((TypeElement) element).filter(ProcessingUtility::isDeclaredInDigitalIDLibrary).filterNot(field -> field.getModifiers().contains(Modifier.STATIC))) { if (!field.getModifiers().contains(Modifier.FINAL)) { errorLogger.log("The read-only type $ may only contain final non-static fields.", SourcePosition.of(field), element); } } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { for (@Nonnull ExecutableElement method : ProcessingUtility.getAllMethods((TypeElement) element).filter(ProcessingUtility::isDeclaredInDigitalIDLibrary).filterNot(method -> method.getModifiers().contains(Modifier.STATIC))) { if (!ProcessingUtility.hasAnnotation(method, Pure.class) && !ProcessingUtility.hasAnnotation(method, PureWithSideEffects.class)) { errorLogger.log("The immutable type $ may only contain pure non-static methods.", SourcePosition.of(method), element); } } for (@Nonnull VariableElement field : ProcessingUtility.getAllFields((TypeElement) element).filter(ProcessingUtility::isDeclaredInDigitalIDLibrary).filterNot(field -> field.getModifiers().contains(Modifier.STATIC))) { if (!field.getModifiers().contains(Modifier.FINAL)) { errorLogger.log("The immutable type $ may only contain final non-static fields.", SourcePosition.of(field), element); } } }
@Pure @Override public void checkUsage(@Nonnull Element element, @Nonnull AnnotationMirror annotationMirror, @NonCaptured @Modified @Nonnull ErrorLogger errorLogger) { final @Nonnull TypeElement surroundingType = ProcessingUtility.getSurroundingType(element); if (element.getKind() == ElementKind.METHOD) { final @Nonnull ExecutableElement method = (ExecutableElement) element; final @Nonnull Types typeUtils = StaticProcessingEnvironment.getTypeUtils(); if (!element.getModifiers().contains(Modifier.STATIC) || !typeUtils.isSubtype(method.getReturnType(), typeUtils.erasure(surroundingType.asType()))) { errorLogger.log("The annotation $ may only be used on static methods whose return type is a subtype of the surrounding type.", SourcePosition.of(element, annotationMirror), getAnnotationNameWithLeadingAt()); } } else if (element.getKind() == ElementKind.CONSTRUCTOR) { if (ProcessingUtility.getConstructors(surroundingType).isSingle()) { errorLogger.log("The annotation $ may only be used on constructors if there are also other constructors in the same class.", SourcePosition.of(element, annotationMirror), getAnnotationNameWithLeadingAt()); } } else { errorLogger.log("The annotation $ may only be used on methods and constructors.", SourcePosition.of(element, annotationMirror), getAnnotationNameWithLeadingAt()); } for (@Nonnull ExecutableElement executableElement : ProcessingUtility.getConstructors(surroundingType).combine(ProcessingUtility.getMethods(surroundingType))) { if (ProcessingUtility.hasAnnotation(executableElement, Recover.class) && !executableElement.equals(element)) { errorLogger.log("The annotation $ may only be used on at most one executable in the same type.", SourcePosition.of(element, annotationMirror), getAnnotationNameWithLeadingAt()); } } }