@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; }
@Override public Void visitNewArray(NewArrayTree node, Void p) { AnnotatedArrayType type = atypeFactory.getAnnotatedType(node); AnnotatedTypeMirror componentType = type.getComponentType(); if (componentType.hasEffectiveAnnotation(NONNULL) && !isNewArrayAllZeroDims(node) && !isNewArrayInToArray(node) && !TypesUtils.isPrimitive(componentType.getUnderlyingType()) && checker.getLintOption("forbidnonnullarraycomponents", false)) { checker.report( Result.failure("new.array.type.invalid", componentType.getAnnotations(), type.toString()), node); } return super.visitNewArray(node, p); }
/** * 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); } } }
/* * Provided that m is of a type that implements interface java.util.Map: * -Given a call m.containsKey(k), ensures that k is @KeyFor("m") in the thenStore of the transfer result. * -Given a call m.put(k, ...), ensures that k is @KeyFor("m") in the thenStore and elseStore of the transfer result. */ @Override public TransferResult<CFValue, CFStore> visitMethodInvocation( MethodInvocationNode node, TransferInput<CFValue, CFStore> in) { TransferResult<CFValue, CFStore> result = super.visitMethodInvocation(node, in); String methodName = node.getTarget().getMethod().toString(); // First verify if the method name is containsKey or put. This is an inexpensive check. boolean containsKey = methodName.startsWith("containsKey("); boolean put = methodName.startsWith("put("); if (containsKey || put) { // Now verify that the receiver of the method invocation is of a type // that extends that java.util.Map interface. This is a more expensive check. javax.lang.model.util.Types types = analysis.getTypes(); TypeMirror mapInterfaceTypeMirror = types.erasure( TypesUtils.typeFromClass(types, analysis.getEnv().getElementUtils(), Map.class)); TypeMirror receiverType = types.erasure(node.getTarget().getReceiver().getType()); if (types.isSubtype(receiverType, mapInterfaceTypeMirror)) { FlowExpressionContext flowExprContext = FlowExpressionParseUtil.buildFlowExprContextForUse(node, checker); String mapName = flowExprContext.receiver.toString(); Receiver keyReceiver = flowExprContext.arguments.get(0); KeyForAnnotatedTypeFactory atypeFactory = (KeyForAnnotatedTypeFactory) analysis.getTypeFactory(); LinkedHashSet<String> keyForMaps = new LinkedHashSet<>(); keyForMaps.add(mapName); final CFValue previousKeyValue = in.getValueOfSubNode(node.getArgument(0)); if (previousKeyValue != null) { final AnnotationMirror prevAm = previousKeyValue.getType().getAnnotationInHierarchy(KEYFOR); if (prevAm != null && AnnotationUtils.areSameByClass(prevAm, KeyFor.class)) { keyForMaps.addAll(getKeys(prevAm)); } } AnnotationMirror am = atypeFactory.createKeyForAnnotationMirrorWithValue(keyForMaps); if (containsKey) { ConditionalTransferResult<CFValue, CFStore> conditionalResult = (ConditionalTransferResult<CFValue, CFStore>) result; conditionalResult.getThenStore().insertValue(keyReceiver, am); } else if (put) { result.getThenStore().insertValue(keyReceiver, am); result.getElseStore().insertValue(keyReceiver, am); } } } return result; }