@Override public Void visitTypeCast(TypeCastTree tree, AnnotatedTypeMirror type) { if (isUnderlyingTypeAValue(type)) { AnnotatedTypeMirror castedAnnotation = getAnnotatedType(tree.getExpression()); List<?> values = getValues(castedAnnotation, type.getUnderlyingType()); type.replaceAnnotation(resultAnnotationHandler(type.getUnderlyingType(), values, tree)); } else if (type.getKind() == TypeKind.ARRAY) { if (tree.getExpression().getKind() == Kind.NULL_LITERAL) { type.replaceAnnotation(BOTTOMVAL); } } return null; }
@Override public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) { List<? extends ExpressionTree> dimensions = tree.getDimensions(); List<? extends ExpressionTree> initializers = tree.getInitializers(); // Dimensions provided if (!dimensions.isEmpty()) { handleDimensions(dimensions, (AnnotatedArrayType) type); } else { // Initializer used handleInitalizers(initializers, (AnnotatedArrayType) type); AnnotationMirror newQual; Class<?> clazz = ValueCheckerUtils.getClassFromType(type.getUnderlyingType()); String stringVal = null; if (clazz.equals(byte[].class)) { stringVal = getByteArrayStringVal(initializers); } else if (clazz.equals(char[].class)) { stringVal = getCharArrayStringVal(initializers); } if (stringVal != null) { newQual = createStringAnnotation(Collections.singletonList(stringVal)); type.replaceAnnotation(newQual); } } return null; }
/** * Determine the type of a field access (implicit or explicit) based on the receiver type and the * declared annotations for the field. * * @param type Type of the field access expression * @param declaredFieldAnnotations Annotations on the element. * @param receiverType Inferred annotations of the receiver */ private void computeFieldAccessType( AnnotatedTypeMirror type, Collection<? extends AnnotationMirror> declaredFieldAnnotations, AnnotatedTypeMirror receiverType, AnnotatedTypeMirror fieldAnnotations, Element element) { // not necessary for primitive fields if (TypesUtils.isPrimitive(type.getUnderlyingType())) { return; } // not necessary if there is an explicit UnknownInitialization // annotation on the field if (AnnotationUtils.containsSameIgnoringValues( fieldAnnotations.getAnnotations(), UNCLASSIFIED)) { return; } if (isUnclassified(receiverType) || isFree(receiverType)) { TypeMirror fieldDeclarationType = element.getEnclosingElement().asType(); boolean isInitializedForFrame = isInitializedForFrame(receiverType, fieldDeclarationType); if (isInitializedForFrame) { // The receiver is initialized for this frame. // Change the type of the field to @UnknownInitialization or @Raw so that // anything can be assigned to this field. type.replaceAnnotation(UNCLASSIFIED); } else if (computingAnnotatedTypeMirrorOfLHS) { // The receiver is not initialized for this frame, but the type of a lhs is being computed. // Change the type of the field to @UnknownInitialization or @Raw so that // anything can be assigned to this field. type.replaceAnnotation(UNCLASSIFIED); } else { // The receiver is not initialized for this frame and the type being computed is not a LHS. // Replace all annotations with the top annotation for that hierarchy. type.clearAnnotations(); type.addAnnotations(qualHierarchy.getTopAnnotations()); } if (!AnnotationUtils.containsSame(declaredFieldAnnotations, NOT_ONLY_COMMITTED) || !useFbc) { // add root annotation for all other hierarchies, and // Committed for the commitment hierarchy type.replaceAnnotation(COMMITTED); } } }
/** * If any constant-value annotation has > MAX_VALUES number of values provided, treats the * value as UnknownVal. Works together with ValueVisitor.visitAnnotation, which issues a warning * to the user in this case. */ private void replaceWithUnknownValIfTooManyValues(AnnotatedTypeMirror atm) { AnnotationMirror anno = atm.getAnnotationInHierarchy(UNKNOWNVAL); if (anno != null && anno.getElementValues().size() > 0) { List<Object> values = AnnotationUtils.getElementValueArray(anno, "value", Object.class, false); if (values != null && values.size() > MAX_VALUES) { atm.replaceAnnotation(UNKNOWNVAL); } } }
@Override public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) { if (TreeUtils.isFieldAccess(tree) && isUnderlyingTypeAValue(type)) { VariableElement elem = (VariableElement) InternalUtils.symbol(tree); Object value = elem.getConstantValue(); if (value != null) { // compile time constant type.replaceAnnotation( resultAnnotationHandler( type.getUnderlyingType(), Collections.singletonList(value), tree)); return null; } if (ElementUtils.isStatic(elem) && ElementUtils.isFinal(elem)) { Element e = InternalUtils.symbol(tree.getExpression()); if (e != null) { String classname = ElementUtils.getQualifiedClassName(e).toString(); String fieldName = tree.getIdentifier().toString(); value = evalutator.evaluateStaticFieldAccess(classname, fieldName, tree); if (value != null) type.replaceAnnotation( resultAnnotationHandler( type.getUnderlyingType(), Collections.singletonList(value), tree)); return null; } } if (tree.getIdentifier().toString().equals("length")) { AnnotatedTypeMirror receiverType = getAnnotatedType(tree.getExpression()); if (receiverType.getKind() == TypeKind.ARRAY) { AnnotationMirror arrayAnno = receiverType.getAnnotation(ArrayLen.class); if (arrayAnno != null) { // array.length, where array : @ArrayLen(x) List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno); type.replaceAnnotation(createNumberAnnotationMirror(new ArrayList<Number>(lengths))); return null; } } } } return null; }
public void handle(MethodInvocationTree tree, AnnotatedExecutableType method) { if (TreeUtils.isMethodInvocation(tree, systemGetProperty, env)) { List<? extends ExpressionTree> args = tree.getArguments(); assert args.size() == 1; ExpressionTree arg = args.get(0); if (arg.getKind() == Tree.Kind.STRING_LITERAL) { String literal = (String) ((LiteralTree) arg).getValue(); if (systemProperties.contains(literal)) { AnnotatedTypeMirror type = method.getReturnType(); type.replaceAnnotation(factory.NONNULL); } } } }
@Override public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) { if (isUnderlyingTypeAValue(type)) { switch (tree.getKind()) { case BOOLEAN_LITERAL: AnnotationMirror boolAnno = createBooleanAnnotation(Collections.singletonList((Boolean) tree.getValue())); type.replaceAnnotation(boolAnno); return null; case CHAR_LITERAL: AnnotationMirror charAnno = createCharAnnotation(Collections.singletonList((Character) tree.getValue())); type.replaceAnnotation(charAnno); return null; case DOUBLE_LITERAL: AnnotationMirror doubleAnno = createNumberAnnotationMirror( Collections.<Number>singletonList((Double) tree.getValue())); type.replaceAnnotation(doubleAnno); return null; case FLOAT_LITERAL: AnnotationMirror floatAnno = createNumberAnnotationMirror( Collections.<Number>singletonList((Float) tree.getValue())); type.replaceAnnotation(floatAnno); return null; case INT_LITERAL: AnnotationMirror intAnno = createNumberAnnotationMirror( Collections.<Number>singletonList((Integer) tree.getValue())); type.replaceAnnotation(intAnno); return null; case LONG_LITERAL: AnnotationMirror longAnno = createNumberAnnotationMirror( Collections.<Number>singletonList((Long) tree.getValue())); type.replaceAnnotation(longAnno); return null; case STRING_LITERAL: AnnotationMirror stringAnno = createStringAnnotation(Collections.singletonList((String) tree.getValue())); type.replaceAnnotation(stringAnno); return null; default: return null; } } return null; }
private AnnotatedTypeMirror postFixDouble(AnnotatedTypeMirror anno, boolean increment) { List<Double> values = getDoubleValues(anno.getAnnotation(DoubleVal.class)); List<? extends Number> castedValues = NumberUtils.castNumbers(anno.getUnderlyingType(), values); List<Double> results = new ArrayList<>(); for (Number value : castedValues) { NumberMath<?> number = NumberMath.getNumberMath(value); if (increment) { results.add(number.minus(1).doubleValue()); } else { results.add(number.plus(1).doubleValue()); } } anno.replaceAnnotation(createDoubleValAnnotation(results)); return anno; }
@Override public Void visitNewClass(NewClassTree node, AnnotatedTypeMirror p) { super.visitNewClass(node, p); if (useFbc) { boolean allCommitted = true; Type type = ((JCTree) node).type; for (ExpressionTree a : node.getArguments()) { final AnnotatedTypeMirror t = getAnnotatedType(a); allCommitted &= (isCommitted(t) || isFbcBottom(t)); } if (!allCommitted) { p.replaceAnnotation(createFreeAnnotation(type)); } } return null; }
@Override public Void visitMethodInvocation(MethodInvocationTree tree, AnnotatedTypeMirror type) { if (isUnderlyingTypeAValue(type) && methodIsStaticallyExecutable(TreeUtils.elementFromUse(tree))) { // Get argument values List<? extends ExpressionTree> arguments = tree.getArguments(); ArrayList<List<?>> argValues; if (arguments.size() > 0) { argValues = new ArrayList<List<?>>(); for (ExpressionTree argument : arguments) { AnnotatedTypeMirror argType = getAnnotatedType(argument); List<?> values = getValues(argType, argType.getUnderlyingType()); if (values.isEmpty()) { // values aren't known, so don't try to evaluate the // method return null; } argValues.add(values); } } else { argValues = null; } // Get receiver values AnnotatedTypeMirror receiver = getReceiverType(tree); List<?> receiverValues; if (receiver != null && !ElementUtils.isStatic(TreeUtils.elementFromUse(tree))) { receiverValues = getValues(receiver, receiver.getUnderlyingType()); if (receiverValues.isEmpty()) { // values aren't known, so don't try to evaluate the // method return null; } } else { receiverValues = null; } // Evaluate method List<?> returnValues = evalutator.evaluteMethodCall(argValues, receiverValues, tree); AnnotationMirror returnType = resultAnnotationHandler(type.getUnderlyingType(), returnValues, tree); type.replaceAnnotation(returnType); } return null; }
@Override public Void visitNewClass(NewClassTree tree, AnnotatedTypeMirror type) { boolean wrapperClass = TypesUtils.isBoxedPrimitive(type.getUnderlyingType()) || TypesUtils.isDeclaredOfName(type.getUnderlyingType(), "java.lang.String"); if (wrapperClass || (isUnderlyingTypeAValue(type) && methodIsStaticallyExecutable(TreeUtils.elementFromUse(tree)))) { // get arugment values List<? extends ExpressionTree> arguments = tree.getArguments(); ArrayList<List<?>> argValues; if (arguments.size() > 0) { argValues = new ArrayList<List<?>>(); for (ExpressionTree argument : arguments) { AnnotatedTypeMirror argType = getAnnotatedType(argument); List<?> values = getValues(argType, argType.getUnderlyingType()); if (values.isEmpty()) { // values aren't known, so don't try to evaluate the // method return null; } argValues.add(values); } } else { argValues = null; } // Evaluate method List<?> returnValues = evalutator.evaluteConstrutorCall(argValues, tree, type.getUnderlyingType()); AnnotationMirror returnType = resultAnnotationHandler(type.getUnderlyingType(), returnValues, tree); type.replaceAnnotation(returnType); } return null; }