Skip to content

Commit

Permalink
Javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
pauxus committed Oct 20, 2023
1 parent c1a5433 commit c30a82f
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,17 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Designates the annotated member of an annotation is not allowed when the annotation is placed on the given
* element types.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@KlumCastValidator("com.blackbuild.klum.cast.checks.impl.MemberTargetFilter")
public @interface NotOn {
/**
* The element types on which the annotated member is not allowed.
* @return the element types on which the annotated member is not allowed.
*/
ElementType[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@
@Retention(RetentionPolicy.RUNTIME)
@KlumCastValidator("com.blackbuild.klum.cast.checks.impl.NotTogetherWithCheck")
public @interface NotTogetherWith {
/**
* The annotations that should not be used together with the annotated annotation.
* @return the annotations that should not be used together with the annotated annotation.
*/
Class<? extends Annotation>[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,17 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Checks that the annotated methods has exactly the given number of parameters. Note that if the annotated element is no method, the validation is ignored.
*/
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@KlumCastValidator(type = NumberOfParameters.Check.class)
public @interface NumberOfParameters {
/**
* The number of parameters the annotated method must have.
* @return the number of parameters the annotated method must have.
*/
int value();

class Check extends KlumCastCheck<NumberOfParameters> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Designates the annotated member of an annotation is only allowed when the annotation is placed on the given element types.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@KlumCastValidator("com.blackbuild.klum.cast.checks.impl.MemberTargetFilter")
public @interface OnlyOn {
/**
* The element types on which the annotated member is allowed.
* @return the element types on which the annotated member is allowed.
*/
ElementType[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* If the target annotation is placed on a method, the method must have the specified parameter types. Single value
* elements can be null to indicate that the parameter type is not checked. If the annotated method has fewer parameters
* that the number of specified parameter types, the extra parameter types are ignored unless strict is set to true.
*/
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@KlumCastValidator("com.blackbuild.klum.cast.checks.impl.ParameterTypesCheck")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,34 +64,52 @@ public void setMemberName(@Nullable String memberName) {

/**
* Performs the actual check. Checks if the check is applicable for the given target and if so,
* delegates to the doCheck method, wrapping any exceptions thrown in an Error object.
* delegates to the doCheck method, wrapping any exceptions thrown in an ErrorMessage object.
* <p>
* Usually it is more convenient to override doCheck instead of this method.
*
* @param annotationToCheck The annotation whose placement is validated
* @param target the target where the annotation to check is placed
* @return an Optional Error object if the check failed, empty if the check succeeded
* @return an Optional ErrorMessage object if the check failed, empty if the check succeeded
*/
public Optional<Error> check(AnnotationNode annotationToCheck, AnnotatedNode target) {
public Optional<ErrorMessage> check(AnnotationNode annotationToCheck, AnnotatedNode target) {
try {
if (isValidFor(target))
doCheck(annotationToCheck, target);
return Optional.empty();
} catch (ValidationException e) {
return Optional.of(e.toError(annotationToCheck));
} catch (RuntimeException e) {
return Optional.of(new Error(e.getMessage(), annotationToCheck));
return Optional.of(new ErrorMessage(e.getMessage(), annotationToCheck));
}
}

/**
* Checks if the check is applicable for the given target. By default, this is always true, but can be overidden for
* quick testing.
* @param target The target where the annotation to validate is placed.
* @return true if the check is applicable for the given target.
*/
protected boolean isValidFor(AnnotatedNode target) {
return true;
}

/**
* Performs the actual check. If the check fails, a {@link ValidationException} or any Runtime exception should be thrown.
* @param annotationToCheck The annotation whose placement is validated
* @param target the target where the annotation to check is placed
* @throws ValidationException if the check fails
*/
protected abstract void doCheck(AnnotationNode annotationToCheck, AnnotatedNode target) throws ValidationException;

public static class Error {
/**
* Encapsulates an error message and the node where the error occurred. Usually needs not to be used directly
*/
public static class ErrorMessage {
public final String message;
public final ASTNode node;

public Error(String message, ASTNode node) {
public ErrorMessage(String message, ASTNode node) {
this.message = message;
this.node = node;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@

import org.codehaus.groovy.ast.ASTNode;

public class ValidationException extends RuntimeException {
/**
* Exception that can be thrown to signal a validation error. Currently the only difference to a normal exception is
* the option to provide an ASTNode that is used as the position of the error (which defaults to the validated annotation).
*/
public class ValidationException extends Exception {

private final ASTNode position;
public ValidationException(String message) {
Expand All @@ -49,7 +53,7 @@ public ValidationException(Throwable cause) {
this(cause.getMessage(), cause, null);
}

public KlumCastCheck.Error toError(ASTNode position) {
return new KlumCastCheck.Error(getMessage(), this.position != null ? this.position : position);
public KlumCastCheck.ErrorMessage toError(ASTNode position) {
return new KlumCastCheck.ErrorMessage(getMessage(), this.position != null ? this.position : position);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ protected void doCheck(AnnotationNode annotationToCheck, AnnotatedNode target) {
for (int i = 0; i < method.getParameters().length; i++) {
if (i >= requiredTypes.length)
break;
if (requiredTypes[i] == null)
continue;
if (!AstSupport.isAssignable(method.getParameters()[i], requiredTypes[i]))
throw new IllegalStateException(String.format(
"Parameter %d of method %s is not assignable to %s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class ValidationHandler {

private final AnnotationNode annotationToValidate;
private final AnnotatedNode target;
private final List<KlumCastCheck.Error> errors = new ArrayList<>();
private final List<KlumCastCheck.ErrorMessage> errors = new ArrayList<>();
private String currentMember;

private Annotation currentAnnotation;
Expand All @@ -61,16 +61,16 @@ public static void setStatus(AnnotationNode annotationNode, ValidationHandler.St
annotationNode.setNodeMetaData(METADATA_KEY, status);
}

public static List<KlumCastCheck.Error> validateAnnotation(AnnotationNode annotationToValidate, AnnotatedNode target) {
public static List<KlumCastCheck.ErrorMessage> validateAnnotation(AnnotationNode annotationToValidate, AnnotatedNode target) {
if (alreadyValidated(annotationToValidate))
return Collections.emptyList();
if (!annotationToValidate.getClassNode().isResolved())
return Collections.singletonList(new KlumCastCheck.Error("Validated annotation must have already been compiled", annotationToValidate));
return Collections.singletonList(new KlumCastCheck.ErrorMessage("Validated annotation must have already been compiled", annotationToValidate));

return new ValidationHandler(annotationToValidate, target).validate();
}

private List<KlumCastCheck.Error> validate() {
private List<KlumCastCheck.ErrorMessage> validate() {
doValidate(annotationToValidate.getClassNode().getTypeClass());
validateAnnotationMembers();
setStatus(annotationToValidate, Status.VALIDATED);
Expand Down

0 comments on commit c30a82f

Please sign in to comment.