@Override
 public boolean canContain(DataModelMirror other) {
   Precondition.checkMustNotBeNull(other, "other"); // $NON-NLS-1$
   if (other instanceof ConcreteDataModelMirror) {
     ConcreteDataModelMirror that = (ConcreteDataModelMirror) other;
     return environment.getTypeUtils().isSameType(this.type, that.type);
   }
   if (other instanceof PartialDataModelMirror) {
     PartialDataModelMirror that = (PartialDataModelMirror) other;
     Types typeUtils = environment.getTypeUtils();
     return typeUtils.isSubtype(this.type, that.type.getUpperBound())
         && typeUtils.isSubtype(that.type.getLowerBound(), this.type);
   }
   return false;
 }
  private Set<ConstraintCheckError> checkAnnotationValue(
      TypeElement element, AnnotationMirror annotation) {
    Set<ConstraintCheckError> errors = CollectionHelper.newHashSet();
    AnnotationValue value = annotationApiHelper.getAnnotationValue(annotation, "value");
    TypeMirror valueType = (TypeMirror) value.getValue();
    TypeElement valueElement = (TypeElement) typeUtils.asElement(valueType);

    if (valueElement.getKind().isInterface()
        || valueElement.getModifiers().contains(Modifier.ABSTRACT)) {
      errors.add(
          new ConstraintCheckError(
              element,
              annotation,
              "GROUP_SEQUENCE_PROVIDER_ANNOTATION_VALUE_MUST_BE_AN_IMPLEMENTATION_CLASS"));

    } else {
      // the TypeElement hosting the annotation is a concrete implementation of the
      // DefaultGroupSequenceProvider
      // interface. In that case, we need to check that it has a public default constructor.
      if (!hasPublicDefaultConstructor(valueElement)) {
        errors.add(
            new ConstraintCheckError(
                element,
                annotation,
                "GROUP_SEQUENCE_PROVIDER_ANNOTATION_VALUE_CLASS_MUST_HAVE_DEFAULT_CONSTRUCTOR",
                valueType));
      }
    }

    TypeMirror genericProviderType = retrieveGenericProviderType(valueType);
    if (!typeUtils.isSubtype(element.asType(), genericProviderType)) {
      errors.add(
          new ConstraintCheckError(
              element,
              annotation,
              "GROUP_SEQUENCE_PROVIDER_ANNOTATION_VALUE_DEFINED_PROVIDER_CLASS_WITH_WRONG_TYPE",
              genericProviderType,
              element.asType()));
    }

    return errors;
  }
Esempio n. 3
0
  public Type getType(TypeMirror mirror) {
    if (mirror.getKind() == TypeKind.ERROR) {
      throw new AnnotationProcessingException("Encountered erroneous type " + mirror);
    }

    Type implementationType = getImplementationType(mirror);

    boolean isIterableType = typeUtils.isSubtype(mirror, iterableType);
    boolean isCollectionType = typeUtils.isSubtype(mirror, collectionType);
    boolean isMapType = typeUtils.isSubtype(mirror, mapType);

    boolean isEnumType;
    boolean isInterface;
    String name;
    String packageName;
    String qualifiedName;
    TypeElement typeElement;
    Type componentType;

    if (mirror.getKind() == TypeKind.DECLARED) {
      DeclaredType declaredType = (DeclaredType) mirror;

      isEnumType = declaredType.asElement().getKind() == ElementKind.ENUM;
      isInterface = declaredType.asElement().getKind() == ElementKind.INTERFACE;
      name = declaredType.asElement().getSimpleName().toString();

      typeElement = (TypeElement) declaredType.asElement();

      if (typeElement != null) {
        packageName = elementUtils.getPackageOf(typeElement).getQualifiedName().toString();
        qualifiedName = typeElement.getQualifiedName().toString();
      } else {
        packageName = null;
        qualifiedName = name;
      }

      componentType = null;
    } else if (mirror.getKind() == TypeKind.ARRAY) {
      TypeMirror componentTypeMirror = getComponentType(mirror);

      if (componentTypeMirror.getKind() == TypeKind.DECLARED) {
        DeclaredType declaredType = (DeclaredType) componentTypeMirror;
        TypeElement componentTypeElement = (TypeElement) declaredType.asElement();

        name = componentTypeElement.getSimpleName().toString() + "[]";
        packageName = elementUtils.getPackageOf(componentTypeElement).getQualifiedName().toString();
        qualifiedName = componentTypeElement.getQualifiedName().toString() + "[]";
      } else {
        name = mirror.toString();
        packageName = null;
        qualifiedName = name;
      }

      isEnumType = false;
      isInterface = false;
      typeElement = null;
      componentType = getType(componentTypeMirror);
    } else {
      isEnumType = false;
      isInterface = false;
      name = mirror.toString();
      packageName = null;
      qualifiedName = name;
      typeElement = null;
      componentType = null;
    }

    return new Type(
        typeUtils,
        elementUtils,
        this,
        mirror,
        typeElement,
        getTypeParameters(mirror, false),
        implementationType,
        componentType,
        packageName,
        name,
        qualifiedName,
        isInterface,
        isEnumType,
        isIterableType,
        isCollectionType,
        isMapType,
        isImported(name, qualifiedName));
  }
 public boolean isInitializedForFrame(AnnotatedTypeMirror type, TypeMirror frame) {
   AnnotationMirror initializationAnno = type.getEffectiveAnnotationInHierarchy(UNCLASSIFIED);
   TypeMirror typeFrame = getTypeFrameFromAnnotation(initializationAnno);
   Types types = processingEnv.getTypeUtils();
   return types.isSubtype(typeFrame, frame);
 }
  /*
   * 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;
  }