org.checkerframework.checker.nullness.NullnessValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java's type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.checker.nullness;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.PolyNull;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAbstractValue;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.javacutil.AnnotationMirrorSet;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TypesUtils;
/**
* Behaves just like {@link CFValue}, but additionally tracks whether at this point {@link PolyNull}
* is known to be {@link NonNull} or {@link Nullable} (or not known to be either)
*/
public class NullnessValue extends CFAbstractValue {
/** True if, at this point, {@link PolyNull} is known to be {@link NonNull}. */
protected boolean isPolyNullNonNull;
/** True if, at this point, {@link PolyNull} is known to be {@link Nullable}. */
protected boolean isPolyNullNull;
/**
* Creates a new NullnessValue.
*
* @param analysis the analysis
* @param annotations the annotations
* @param underlyingType the underlying type
*/
public NullnessValue(
CFAbstractAnalysis analysis,
AnnotationMirrorSet annotations,
TypeMirror underlyingType) {
super(analysis, annotations, underlyingType);
}
@Override
protected NullnessValue upperBound(
@Nullable NullnessValue other, TypeMirror upperBoundTypeMirror, boolean shouldWiden) {
NullnessValue result = super.upperBound(other, upperBoundTypeMirror, shouldWiden);
AnnotationMirror resultNullableAnno =
analysis.getTypeFactory().getAnnotationByClass(result.annotations, Nullable.class);
if (resultNullableAnno != null && other != null) {
if ((this.isPolyNullNonNull
&& this.containsNonNullOrPolyNull()
&& other.isPolyNullNull
&& other.containsNullableOrPolyNull())
|| (other.isPolyNullNonNull
&& other.containsNonNullOrPolyNull()
&& this.isPolyNullNull
&& this.containsNullableOrPolyNull())) {
result.annotations.remove(resultNullableAnno);
result.annotations.add(((NullnessAnnotatedTypeFactory) analysis.getTypeFactory()).POLYNULL);
}
}
return result;
}
/**
* Returns true if this value contans {@code @NonNull} or {@code @PolyNull}.
*
* @return true if this value contans {@code @NonNull} or {@code @PolyNull}
*/
@Pure
private boolean containsNonNullOrPolyNull() {
return analysis.getTypeFactory().containsSameByClass(annotations, NonNull.class)
|| analysis.getTypeFactory().containsSameByClass(annotations, PolyNull.class);
}
/**
* Returns true if this value contans {@code @Nullable} or {@code @PolyNull}.
*
* @return true if this value contans {@code @Nullable} or {@code @PolyNull}
*/
@Pure
private boolean containsNullableOrPolyNull() {
return analysis.getTypeFactory().containsSameByClass(annotations, Nullable.class)
|| analysis.getTypeFactory().containsSameByClass(annotations, PolyNull.class);
}
@SideEffectFree
@Override
public String toStringSimple() {
return "NV{"
+ AnnotationUtils.toStringSimple(annotations)
+ ", "
+ TypesUtils.simpleTypeName(underlyingType)
+ ", poly nn/n="
+ (isPolyNullNonNull ? 't' : 'f')
+ '/'
+ (isPolyNullNull ? 't' : 'f')
+ '}';
}
}