org.checkerframework.checker.nullness.qual.EnsuresNonNullIf Maven / Gradle / Ivy
package org.checkerframework.checker.nullness.qual;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.checkerframework.framework.qual.ConditionalPostconditionAnnotation;
import org.checkerframework.framework.qual.InheritedAnnotation;
/**
* Indicates that the given expressions are non-null, if the method returns the given result (either
* true or false).
*
* Here are ways this conditional postcondition annotation can be used:
*
*
Method parameters: A common example is that the {@code equals} method is annotated as
* follows:
*
*
{@code @EnsuresNonNullIf(expression="#1", result=true)
* public boolean equals(@Nullable Object obj) { ... }}
*
* because, if {@code equals} returns true, then the first (#1) argument to {@code equals} was not
* null.
*
* Fields: The value expressions can refer to fields, even private ones. For example:
*
*
{@code @EnsuresNonNullIf(expression="this.derived", result=true)
* public boolean isDerived() {
* return (this.derived != null);
* }}
*
* As another example, an {@code Iterator} may cache the next value that will be returned, in which
* case its {@code hasNext} method could be annotated as:
*
* {@code @EnsuresNonNullIf(expression="next_cache", result=true)
* public boolean hasNext() {
* if (next_cache == null) return false;
* ...
* }}
*
* An {@code EnsuresNonNullIf} annotation that refers to a private field is useful for verifying
* that client code performs needed checks in the right order, even if the client code cannot
* directly affect the field.
*
* Method calls: If {@link Class#isArray()} returns true, then {@link
* Class#getComponentType()} returns non-null. You can express this relationship as:
*
*
{@code @EnsuresNonNullIf(expression="getComponentType()", result=true)
* public native @Pure boolean isArray();}
*
*
* You cannot write two {@code @EnsuresNonNullIf} annotations on a single method; to get the effect
* of
*
*
* @EnsuresNonNullIf(expression="outputFile", result=true)
* @EnsuresNonNullIf(expression="memoryOutputStream", result=false)
* public boolean isThresholdExceeded() { ... }
*
*
* you need to instead write
*
*
* @EnsuresQualifiersIf({
* @EnsuresQualifierIf(result=true, qualifier=NonNull.class, expression="outputFile"),
* @EnsuresQualifierIf(result=false, qualifier=NonNull.class, expression="memoryOutputStream")
* })
*
*
* @see NonNull
* @see EnsuresNonNull
* @see org.checkerframework.checker.nullness.NullnessChecker
* @checker_framework.manual #nullness-checker Nullness Checker
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@ConditionalPostconditionAnnotation(qualifier = NonNull.class)
@InheritedAnnotation
public @interface EnsuresNonNullIf {
/**
* Java expression(s) that are non-null after the method returns the given result.
*
* @checker_framework.manual #java-expressions-as-arguments Syntax of Java expressions
*/
String[] expression();
/** The return value of the method that needs to hold for the postcondition to hold. */
boolean result();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy