use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueAnnotatedTypeFactory method createArrayLengthResultAnnotation.
/**
* Returns a constant value annotation for a length of an array or string type with a constant
* value annotation
*/
AnnotationMirror createArrayLengthResultAnnotation(AnnotatedTypeMirror receiverType) {
AnnotationMirror arrayAnno = receiverType.getAnnotationInHierarchy(UNKNOWNVAL);
if (AnnotationUtils.areSameByClass(arrayAnno, ArrayLen.class)) {
// array.length, where array : @ArrayLen(x)
List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno);
return createNumberAnnotationMirror(new ArrayList<>(lengths));
}
// Check for an ArrayLenRange annotation.
if (AnnotationUtils.areSameByClass(arrayAnno, ArrayLenRange.class)) {
// array.length, where array : @ArrayLenRange(x)
Range range = getRange(arrayAnno);
return createIntRangeAnnotation(range);
}
if (AnnotationUtils.areSameByClass(arrayAnno, StringVal.class)) {
List<String> strings = ValueAnnotatedTypeFactory.getStringValues(arrayAnno);
List<Integer> lengths = ValueCheckerUtils.getLengthsForStringValues(strings);
return createNumberAnnotationMirror(new ArrayList<>(lengths));
}
return createIntRangeAnnotation(0, Integer.MAX_VALUE);
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueCheckerUtils method getValuesCastedToType.
/**
* Get a list of values of annotation, and then cast them to a given type
*
* @param anno the annotation that contains values
* @param castTo the type that is casted to
* @return a list of values after the casting
*/
public static List<?> getValuesCastedToType(AnnotationMirror anno, TypeMirror castTo) {
Class<?> castType = ValueCheckerUtils.getClassFromType(castTo);
List<?> values = null;
if (AnnotationUtils.areSameByClass(anno, DoubleVal.class)) {
values = convertDoubleVal(anno, castType, castTo);
} else if (AnnotationUtils.areSameByClass(anno, IntVal.class)) {
List<Long> longs = ValueAnnotatedTypeFactory.getIntValues(anno);
values = convertIntVal(longs, castType, castTo);
} else if (AnnotationUtils.areSameByClass(anno, IntRange.class)) {
Range range = ValueAnnotatedTypeFactory.getRange(anno);
List<Long> longs = getValuesFromRange(range, Long.class);
values = convertIntVal(longs, castType, castTo);
} else if (AnnotationUtils.areSameByClass(anno, StringVal.class)) {
values = convertStringVal(anno, castType);
} else if (AnnotationUtils.areSameByClass(anno, BoolVal.class)) {
values = convertBoolVal(anno, castType);
} else if (AnnotationUtils.areSameByClass(anno, BottomVal.class)) {
values = new ArrayList<>();
} else if (AnnotationUtils.areSameByClass(anno, UnknownVal.class)) {
values = null;
} else if (AnnotationUtils.areSameByClass(anno, ArrayLen.class)) {
values = new ArrayList<>();
}
return values;
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method getStringValues.
/**
* Returns a list of possible values for {@code subNode}, as casted to a String. Returns null if
* {@code subNode}'s type is top/unknown. Returns an empty list if {@code subNode}'s type is
* bottom.
*/
private List<String> getStringValues(Node subNode, TransferInput<CFValue, CFStore> p) {
CFValue value = p.getValueOfSubNode(subNode);
// @StringVal, @UnknownVal, @BottomVal
AnnotationMirror stringAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), StringVal.class);
if (stringAnno != null) {
return ValueAnnotatedTypeFactory.getStringValues(stringAnno);
}
AnnotationMirror topAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), UnknownVal.class);
if (topAnno != null) {
return null;
}
AnnotationMirror bottomAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), BottomVal.class);
if (bottomAnno != null) {
return new ArrayList<>();
}
// @IntVal, @IntRange, @DoubleVal, @BoolVal (have to be converted to string)
List<? extends Object> values;
AnnotationMirror numberAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), BoolVal.class);
if (numberAnno != null) {
values = getBooleanValues(subNode, p);
} else if (subNode.getType().getKind() == TypeKind.CHAR) {
values = getCharValues(subNode, p);
} else if (subNode instanceof StringConversionNode) {
return getStringValues(((StringConversionNode) subNode).getOperand(), p);
} else if (isIntRange(subNode, p)) {
Range range = getIntRange(subNode, p);
List<Long> longValues = ValueCheckerUtils.getValuesFromRange(range, Long.class);
values = NumberUtils.castNumbers(subNode.getType(), longValues);
} else {
values = getNumericalValues(subNode, p);
}
if (values == null) {
return null;
}
List<String> stringValues = new ArrayList<>();
for (Object o : values) {
stringValues.add(o.toString());
}
// Empty list means bottom value
return stringValues.isEmpty() ? Collections.singletonList("null") : stringValues;
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method getCharValues.
/**
* Get possible char values from annotation @IntRange or @IntVal.
*/
private List<Character> getCharValues(Node subNode, TransferInput<CFValue, CFStore> p) {
CFValue value = p.getValueOfSubNode(subNode);
AnnotationMirror intAnno;
intAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), IntVal.class);
if (intAnno != null) {
return ValueAnnotatedTypeFactory.getCharValues(intAnno);
}
if (atypefactory.isIntRange(value.getAnnotations())) {
intAnno = atypefactory.getQualifierHierarchy().findAnnotationInHierarchy(value.getAnnotations(), atypefactory.UNKNOWNVAL);
Range range = ValueAnnotatedTypeFactory.getRange(intAnno);
return ValueCheckerUtils.getValuesFromRange(range, Character.class);
}
return new ArrayList<>();
}
use of org.checkerframework.common.value.util.Range in project checker-framework by typetools.
the class ValueTransfer method getStringLengths.
/**
* Returns a list of possible lengths for {@code subNode}, as casted to a String. Returns null
* if {@code subNode}'s type is top/unknown. Returns an empty list if {@code subNode}'s type is
* bottom.
*/
private List<Integer> getStringLengths(Node subNode, TransferInput<CFValue, CFStore> p) {
CFValue value = p.getValueOfSubNode(subNode);
// @ArrayLen
AnnotationMirror arrayLenAnno = AnnotationUtils.getAnnotationByClass(value.getAnnotations(), ArrayLen.class);
if (arrayLenAnno != null) {
return ValueAnnotatedTypeFactory.getArrayLength(arrayLenAnno);
}
// @BottomVal
if (AnnotationUtils.containsSameByClass(value.getAnnotations(), BottomVal.class)) {
return new ArrayList<>();
}
TypeKind subNodeTypeKind = subNode.getType().getKind();
// handle values converted to string (characters, bytes, shorts, ints with @IntRange)
if (subNode instanceof StringConversionNode) {
return getStringLengths(((StringConversionNode) subNode).getOperand(), p);
} else if (subNodeTypeKind == TypeKind.CHAR) {
// characters always have length 1
return Collections.singletonList(1);
} else if (isIntRange(subNode, p)) {
// Try to get a list of lengths from a range of integer values converted to string
// @IntVal is not checked for, because if it is present, we would already have the
// actual string values
Range lengthRange = getIntRangeStringLengthRange(subNode, p);
return ValueCheckerUtils.getValuesFromRange(lengthRange, Integer.class);
} else if (subNodeTypeKind == TypeKind.BYTE) {
// bytes are between 1 and 4 characters long
return ValueCheckerUtils.getValuesFromRange(new Range(1, 4), Integer.class);
} else if (subNodeTypeKind == TypeKind.SHORT) {
// shorts are between 1 and 6 characters long
return ValueCheckerUtils.getValuesFromRange(new Range(1, 6), Integer.class);
} else {
return null;
}
}
Aggregations