public boolean isSubtypeOneLevel(AnnotatedTypeMirror sup, AnnotatedTypeMirror sub) {
    // Current implementation only need to deal with one level
    // Err... cannot handle type variables quite yet
    if (sup.getKind() == TypeKind.TYPEVAR
        || sup.getKind() == TypeKind.WILDCARD
        || sub.getKind() == TypeKind.TYPEVAR
        || sub.getKind() == TypeKind.WILDCARD) return true;

    // TODO: Need to handle Generics and Arrays
    if (sup.hasAnnotation(READONLY)
        || sup.hasAnnotation(PLACE_HOLDER)
        || sub.hasAnnotation(PLACE_HOLDER)) return true;
    else if (sup.hasAnnotation(I)) {
      // t1 is a subtype of t2, if and only they have the same
      // immutability argument
      if (!sub.hasAnnotation(I)) return false;

      AnnotationUtils annoUtils = new AnnotationUtils(this.env);
      String t1Arg =
          annoUtils.parseStringValue(
              sub.getAnnotation(I.class.getCanonicalName()), IMMUTABILITY_KEY);
      String t2Arg =
          annoUtils.parseStringValue(
              sup.getAnnotation(I.class.getCanonicalName()), IMMUTABILITY_KEY);

      return ((t1Arg != null) && (t2Arg != null) && t1Arg.equals(t2Arg));
    }

    return ((sup.hasAnnotation(IMMUTABLE) && sub.hasAnnotation(IMMUTABLE))
        || (sup.hasAnnotation(MUTABLE) && sub.hasAnnotation(MUTABLE))
        || (sup.hasAnnotation(ASSIGNS_FIELDS) && sub.hasAnnotation(ASSIGNS_FIELDS))
        || (sup.hasAnnotation(ASSIGNS_FIELDS) && sub.hasAnnotation(MUTABLE)));
  }
 protected SFlowGraphQualifierHierarchy(GraphFactory f) {
   super(f);
   reimQuals = AnnotationUtils.createAnnotationSet();
   reimQuals.add(SFlowChecker.READONLY);
   reimQuals.add(SFlowChecker.POLYREAD);
   reimQuals.add(SFlowChecker.MUTABLE);
 }
Example #3
0
  /**
   * Returns the type qualifier hierarchy graph to be used by this processor.
   *
   * <p>The implementation builds the type qualifier hierarchy for the {@link
   * #getSupportedTypeQualifiers()} using the meta-annotations found in them. The current
   * implementation returns an instance of {@code GraphQualifierHierarchy}.
   *
   * <p>Subclasses may override this method to express any relationships that cannot be inferred
   * using meta-annotations (e.g. due to lack of meta-annotations).
   *
   * @return an annotation relation tree representing the supported qualifiers
   */
  protected QualifierHierarchy createQualifierHierarchy() {
    MultiGraphQualifierHierarchy.MultiGraphFactory factory = this.createQualifierHierarchyFactory();
    Elements elements = processingEnv.getElementUtils();

    for (Class<? extends Annotation> typeQualifier : getSupportedTypeQualifiers()) {
      AnnotationMirror typeQualifierAnno = AnnotationUtils.fromClass(elements, typeQualifier);
      assert typeQualifierAnno != null : "Loading annotation \"" + typeQualifier + "\" failed!";
      factory.addQualifier(typeQualifierAnno);
      // Polymorphic qualifiers can't declare their supertypes.
      // An error is raised if one is present.
      if (typeQualifier.getAnnotation(PolymorphicQualifier.class) != null) {
        if (typeQualifier.getAnnotation(SubtypeOf.class) != null) {
          // This is currently not supported. At some point we might add
          // polymorphic qualifiers with upper and lower bounds.
          errorAbort(
              "BaseTypeChecker: "
                  + typeQualifier
                  + " is polymorphic and specifies super qualifiers. "
                  + "Remove the @checkers.quals.SubtypeOf or @checkers.quals.PolymorphicQualifier annotation from it.");
        }
        continue;
      }
      if (typeQualifier.getAnnotation(SubtypeOf.class) == null) {
        errorAbort(
            "BaseTypeChecker: "
                + typeQualifier
                + " does not specify its super qualifiers. "
                + "Add an @checkers.quals.SubtypeOf annotation to it.");
      }
      Class<? extends Annotation>[] superQualifiers =
          typeQualifier.getAnnotation(SubtypeOf.class).value();
      for (Class<? extends Annotation> superQualifier : superQualifiers) {
        AnnotationMirror superAnno = null;
        superAnno = AnnotationUtils.fromClass(elements, superQualifier);
        factory.addSubtype(typeQualifierAnno, superAnno);
      }
    }

    QualifierHierarchy hierarchy = factory.build();
    if (hierarchy.getTypeQualifiers().size() < 1) {
      errorAbort(
          "BaseTypeChecker: invalid qualifier hierarchy: hierarchy requires at least one annotation: "
              + hierarchy.getTypeQualifiers());
    }

    return hierarchy;
  }
Example #4
0
 @Override
 public boolean isSubtype(AnnotationMirror rhs, AnnotationMirror lhs) {
   if (AnnotationUtils.areSameIgnoringValues(lhs, KEYFOR)
       && AnnotationUtils.areSameIgnoringValues(rhs, KEYFOR)) {
     // If they are both KeyFor annotations, they have to be equal.
     // TODO: or one a subset of the maps of the other? Ordering of maps?
     return AnnotationUtils.areSame(lhs, rhs);
   }
   // Ignore annotation values to ensure that annotation is in supertype map.
   if (AnnotationUtils.areSameIgnoringValues(lhs, KEYFOR)) {
     lhs = KEYFOR;
   }
   if (AnnotationUtils.areSameIgnoringValues(rhs, KEYFOR)) {
     rhs = KEYFOR;
   }
   return super.isSubtype(rhs, lhs);
 }
  @Override
  public boolean isSubtype(Collection<AnnotationMirror> rhs, Collection<AnnotationMirror> lhs) {
    if (lhs.isEmpty() || rhs.isEmpty()) {
      //            throw new RuntimeException("QualifierHierarchy: Empty annotations in lhs: " +
      // lhs + " or rhs: " + rhs);
      //            System.err.println("WARN: QualifierHierarchy: Empty annotations in lhs: " + lhs
      // + " or rhs: " + rhs + " -- ignored");
      return false;
    }
    // check if lhs contains Readonly and remove all ReIm annotations
    // I don't trust the equal method for AnnotationMirror...
    // FIXME: The following code is very ugly!!!
    boolean isLhsReadonly = false;
    for (Iterator<AnnotationMirror> it = lhs.iterator(); it.hasNext(); ) {
      AnnotationMirror anno = it.next();
      if (anno.toString().equals(SFlowChecker.READONLY.toString())) {
        isLhsReadonly = true;
      }
    }
    Set<AnnotationMirror> rSet = AnnotationUtils.createAnnotationSet();
    rSet.addAll(rhs);
    Set<AnnotationMirror> lSet = AnnotationUtils.createAnnotationSet();
    lSet.addAll(lhs);
    rSet = InferenceUtils.differAnnotations(rSet, reimQuals);
    lSet = InferenceUtils.differAnnotations(lSet, reimQuals);

    for (AnnotationMirror lhsAnno : lSet) {
      for (AnnotationMirror rhsAnno : rSet) {
        if (isLhsReadonly || rhsAnno.toString().equals(SFlowChecker.BOTTOM.toString())) {
          if (isSubtype(rhsAnno, lhsAnno)) {
            return true;
          }
        } else {
          // We enforce equality
          if (rhsAnno.toString().equals(lhsAnno.toString())) return true;
        }
      }
    }
    return false;
  }
 @Override
 public Void visitVariable(VariableTree node, AnnotatedTypeMirror p) {
   typeAnnotator.visit(p);
   VariableElement varElt = TreeUtils.elementFromDeclaration((VariableTree) node);
   if (!p.isAnnotated() && ElementUtils.isStatic(varElt)) {
     p.clearAnnotations();
     Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
     set.add(checker.ANY);
     set.add(checker.PEER);
     annotateConstants(p, set);
   }
   return super.visitVariable(node, p);
 }
 @Override
 public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
   if (!type.isAnnotated()) {
     //				if (type.getKind() == TypeKind.NULL) {
     type.clearAnnotations();
     Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
     set.add(checker.BOTTOM);
     annotateConstants(type, set);
     //				}
     //				else
     //					type.addAnnotation(checker.READONLY);
   }
   return super.visitLiteral(tree, type);
 }
  private void annotateMethod(ExecutableElement methodElt, AnnotatedExecutableType methodType) {
    if (checker.isChecking() || methodType.isAnnotated()) {
      return;
    }
    // First annotate the receiver
    annotateThis(methodType.getReceiverType());

    // If it is from library
    if (checker.isFromLibrary(methodElt)) {
      Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
      set.add(checker.PEER);
      annotateConstants(methodType, set);
    }
    // methodType.isAnnotated() only checks the annotations on methodType,
    // but not the type of its receiver, parameters or return;
    if (!methodType.isAnnotated()) methodType.addAnnotation(checker.BOTTOM);
  }
    @Override
    protected QualifierHierarchy createQualifierHierarchy() {
      if (this.bottom != null) {
        // A special bottom qualifier was provided; go through the existing
        // bottom qualifiers and tie them all to this bottom qualifier.
        Set<AnnotationMirror> bottoms = findBottoms(supertypes, null);
        for (AnnotationMirror abot : bottoms) {
          if (!AnnotationUtils.areSame(bottom, abot)) {
            addSubtype(bottom, abot);
          }
        }

        if (!this.polyQualifiers.isEmpty()) {
          for (AnnotationMirror poly : polyQualifiers.values()) {
            addSubtype(bottom, poly);
          }
        }
      }

      return new SFlowGraphQualifierHierarchy(this);
    }
    @Override
    public Void visitDeclared(AnnotatedDeclaredType type, ElementKind p) {
      Element elt = type.getElement();
      if (!type.isAnnotated()
          && (
          /*checker.isDefaultAnyType(type) ||*/
          elt != null
              && ElementUtils.isStatic(elt)
              && (elt.getKind() == ElementKind.FIELD
                  || elt.getKind() == ElementKind.LOCAL_VARIABLE
                  || elt.getKind() == ElementKind.EXCEPTION_PARAMETER
                  || elt.getKind() == ElementKind.ENUM_CONSTANT
                  || elt.getKind() == ElementKind.PARAMETER))) {
        type.clearAnnotations();
        Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet();
        set.add(checker.ANY);
        if (elt != null && ElementUtils.isStatic(elt)) set.add(checker.PEER);

        annotateConstants(type, set);
      }
      return super.visitDeclared(type, p);
    }
Example #11
0
  @Override
  public void initChecker() {
    super.initChecker();

    KEYFOR = AnnotationUtils.fromClass(processingEnv.getElementUtils(), KeyFor.class);
  }