예제 #1
0
  /*
   * 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;
  }