framework.src.org.checkerframework.common.value.ValueCheckerUtils 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.common.value;
import org.checkerframework.common.value.qual.ArrayLen;
import org.checkerframework.common.value.qual.BoolVal;
import org.checkerframework.common.value.qual.BottomVal;
import org.checkerframework.common.value.qual.DoubleVal;
import org.checkerframework.common.value.qual.IntVal;
import org.checkerframework.common.value.qual.StringVal;
import org.checkerframework.common.value.qual.UnknownVal;
import org.checkerframework.common.value.util.NumberUtils;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TypesUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
public class ValueCheckerUtils {
public static Class getClassFromType(TypeMirror type) {
switch (type.getKind()) {
case INT:
return int.class;
case LONG:
return long.class;
case SHORT:
return short.class;
case BYTE:
return byte.class;
case CHAR:
return char.class;
case DOUBLE:
return double.class;
case FLOAT:
return float.class;
case BOOLEAN:
return boolean.class;
case ARRAY:
return getArrayClassObject(((ArrayType) type).getComponentType());
case DECLARED:
String stringType = TypesUtils.getQualifiedName(
(DeclaredType) type).toString();
if (stringType.equals("")) {
return Object.class;
}
try {
return Class.forName(stringType);
} catch (ClassNotFoundException | UnsupportedClassVersionError e) {
return Object.class;
}
default:
return Object.class;
}
}
public static Class getArrayClassObject(TypeMirror componentType) {
switch (componentType.getKind()) {
case INT:
return int[].class;
case LONG:
return long[].class;
case SHORT:
return short[].class;
case BYTE:
return byte[].class;
case CHAR:
return char[].class;
case DOUBLE:
return double[].class;
case FLOAT:
return float[].class;
case BOOLEAN:
return boolean[].class;
default:
return Object[].class;
}
}
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)) {
values = convertIntVal(anno, 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 = convertBottomVal(anno, castType);
} else if (AnnotationUtils.areSameByClass(anno, UnknownVal.class) ||
AnnotationUtils.areSameByClass(anno, ArrayLen.class)) {
values = new ArrayList<>();
}
return values;
}
private static List convertBottomVal(AnnotationMirror anno,
Class newClass) {
if (newClass == String.class) {
return Collections.singletonList("null");
} else {
return new ArrayList<>();
}
}
private static List convertToStringVal(List origValues) {
List strings = new ArrayList<>();
for (Object value : origValues) {
strings.add(value.toString());
}
return strings;
}
private static List convertBoolVal(AnnotationMirror anno, Class newClass) {
List bools = AnnotationUtils.getElementValueArray(anno,
"value", Boolean.class, true);
if (newClass == String.class) {
return convertToStringVal(bools);
}
return bools;
}
private static List convertStringVal(AnnotationMirror anno,
Class newClass) {
List strings = AnnotationUtils.getElementValueArray(anno,
"value", String.class, true);
if (newClass == byte[].class) {
List bytes = new ArrayList<>();
for (String s : strings) {
bytes.add(s.getBytes());
}
return bytes;
} else if (newClass == char[].class) {
List chars = new ArrayList<>();
for (String s : strings) {
chars.add(s.toCharArray());
}
return chars;
} else if (newClass == Object.class && strings.size() == 1) {
if (strings.get(0).equals("null")) {
return strings;
}
}
return strings;
}
private static List convertIntVal(AnnotationMirror anno, Class newClass, TypeMirror newType) {
List longs = ValueAnnotatedTypeFactory.getIntValues(anno);
if (newClass == String.class) {
return convertToStringVal(longs);
} else if (newClass == Character.class || newClass == char.class) {
List chars = new ArrayList<>();
for (Long l : longs) {
chars.add((char) l.longValue());
}
return chars;
} else if (newClass == Boolean.class) {
throw new UnsupportedOperationException("ValueAnnotatedTypeFactory: can't convert double to boolean");
}
return NumberUtils.castNumbers(newType, longs);
}
private static List convertDoubleVal(AnnotationMirror anno,
Class newClass, TypeMirror newType) {
List doubles = ValueAnnotatedTypeFactory.getDoubleValues(anno);
if (newClass == String.class) {
return convertToStringVal(doubles);
} else if (newClass == Character.class || newClass == char.class) {
List chars = new ArrayList<>();
for (Double l : doubles) {
chars.add((char) l.doubleValue());
}
return chars;
} else if (newClass == Boolean.class) {
throw new UnsupportedOperationException("ValueAnnotatedTypeFactory: can't convert double to boolean");
}
return NumberUtils.castNumbers(newType, doubles);
}
public static > List removeDuplicates(List values) {
Set set = new TreeSet<>(values);
return new ArrayList(set);
}
}