All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.common.value.RangeOrListOfValues Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 3.43.0
Show newest version
package org.checkerframework.common.value;

import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.common.value.qual.ArrayLen;
import org.checkerframework.common.value.qual.ArrayLenRange;
import org.checkerframework.common.value.qual.IntVal;
import org.checkerframework.common.value.util.Range;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.StringsPlume;

/**
 * A mutable abstraction that can be either a range or a list of values that could come from an
 * {@link ArrayLen} or {@link IntVal}. This abstraction reduces the number of cases that {@link
 * ValueTreeAnnotator#handleInitializers(List, AnnotatedTypeMirror.AnnotatedArrayType)} and {@link
 * ValueTreeAnnotator#handleDimensions(List, AnnotatedTypeMirror.AnnotatedArrayType)} must handle.
 *
 * 

Tracks ints in the list, and creates ArrayLen or ArrayLenRange annotations, because it's meant * to be used to reason about ArrayLen and ArrayLenRange values. */ class RangeOrListOfValues { private Range range; private List values; private boolean isRange; public RangeOrListOfValues(List values) { this.values = new ArrayList<>(); isRange = false; addAll(values); } public RangeOrListOfValues(Range range) { this.range = range; isRange = true; } public void add(Range otherRange) { if (isRange) { range = range.union(otherRange); } else { convertToRange(); add(otherRange); } } /** * If this is not a range, adds all members of newValues to the list. Otherwise, extends the range * as appropriate based on the max and min of newValues. If adding newValues to a non-range would * cause the list to become too large, converts this into a range. * *

If reading from an {@link org.checkerframework.common.value.qual.IntRange} annotation, * {@link #convertLongsToInts(List)} should be called before calling this method. * * @param newValues values to add */ public void addAll(List newValues) { if (isRange) { range = range.union(Range.create(newValues)); } else { for (Integer i : newValues) { if (!values.contains(i)) { values.add(i); } } if (values.size() > ValueAnnotatedTypeFactory.MAX_VALUES) { convertToRange(); } } } /** * Produces the most precise annotation that captures the information stored in this * RangeOrListofValues. The result is either a {@link ArrayLen} or a {@link ArrayLenRange}. * * @param atypeFactory the type factory * @return an annotation correspending to this RangeOrListofValues */ public AnnotationMirror createAnnotation(ValueAnnotatedTypeFactory atypeFactory) { if (isRange) { return atypeFactory.createArrayLenRangeAnnotation(range); } else { return atypeFactory.createArrayLenAnnotation(values); } } /** * Converts a Long to an Integer by clipping it to the int range. * * @param l a Long integer * @return the value clipped to the Integer range */ private static Integer convertLongToInt(Long l) { if (l > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else if (l < Integer.MIN_VALUE) { return Integer.MIN_VALUE; } else { return l.intValue(); } } /** * To be called before addAll. Converts Longs to Integers by clipping them to the int range; meant * to be used with ArrayLenRange (which only handles Ints). * * @param newValues a list of Long integers * @return a list of Integers */ public static List convertLongsToInts(List newValues) { return CollectionsPlume.mapList(RangeOrListOfValues::convertLongToInt, newValues); } /** * Transforms this into a range. Fails if there are no values in the list. Has no effect if this * is already a range. */ public void convertToRange() { if (!isRange) { isRange = true; range = Range.create(values); values = null; } } @Override public String toString() { if (isRange) { return range.toString(); } else { if (values.isEmpty()) { return "[]"; } String res = "["; res += StringsPlume.join(", ", values); res += "]"; return res; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy