public ValueAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker);

    BOTTOMVAL = AnnotationUtils.fromClass(elements, BottomVal.class);
    UNKNOWNVAL = AnnotationUtils.fromClass(elements, UnknownVal.class);

    coveredClassStrings = new HashSet<String>(19);
    coveredClassStrings.add("int");
    coveredClassStrings.add("java.lang.Integer");
    coveredClassStrings.add("double");
    coveredClassStrings.add("java.lang.Double");
    coveredClassStrings.add("byte");
    coveredClassStrings.add("java.lang.Byte");
    coveredClassStrings.add("java.lang.String");
    coveredClassStrings.add("char");
    coveredClassStrings.add("java.lang.Character");
    coveredClassStrings.add("float");
    coveredClassStrings.add("java.lang.Float");
    coveredClassStrings.add("boolean");
    coveredClassStrings.add("java.lang.Boolean");
    coveredClassStrings.add("long");
    coveredClassStrings.add("java.lang.Long");
    coveredClassStrings.add("short");
    coveredClassStrings.add("java.lang.Short");
    coveredClassStrings.add("byte[]");

    if (this.getClass().equals(ValueAnnotatedTypeFactory.class)) {
      this.postInit();
    }
  }
 /** Is the annotation {@code anno} an initialization qualifier? */
 protected boolean isInitializationAnnotation(AnnotationMirror anno) {
   assert anno != null;
   return AnnotationUtils.areSameIgnoringValues(anno, UNCLASSIFIED)
       || AnnotationUtils.areSameIgnoringValues(anno, FREE)
       || AnnotationUtils.areSameIgnoringValues(anno, COMMITTED)
       || AnnotationUtils.areSameIgnoringValues(anno, FBCBOTTOM);
 }
예제 #3
0
 public KeyForTransfer(KeyForAnalysis analysis, KeyForSubchecker checker) {
   super(analysis);
   this.analysis = analysis;
   this.checker = checker;
   UNKNOWNKEYFOR =
       AnnotationUtils.fromClass(analysis.getTypeFactory().getElementUtils(), UnknownKeyFor.class);
   KEYFOR = AnnotationUtils.fromClass(analysis.getTypeFactory().getElementUtils(), KeyFor.class);
 }
    /**
     * Determines the least upper bound of a1 and a2. If a1 and a2 are both the same type of Value
     * annotation, then the LUB is the result of taking all values from both a1 and a2 and removing
     * duplicates. If a1 and a2 are not the same type of Value annotation they may still be
     * mergeable because some values can be implicitly cast as others. If a1 and a2 are both in
     * {DoubleVal, IntVal} then they will be converted upwards: IntVal &rarr; DoubleVal to arrive at
     * a common annotation type.
     *
     * @return the least upper bound of a1 and a2
     */
    @Override
    public AnnotationMirror leastUpperBound(AnnotationMirror a1, AnnotationMirror a2) {
      if (!AnnotationUtils.areSameIgnoringValues(getTopAnnotation(a1), getTopAnnotation(a2))) {
        return null;
      } else if (isSubtype(a1, a2)) {
        return a2;
      } else if (isSubtype(a2, a1)) {
        return a1;
      }
      // If both are the same type, determine the type and merge:
      else if (AnnotationUtils.areSameIgnoringValues(a1, a2)) {
        List<Object> a1Values =
            AnnotationUtils.getElementValueArray(a1, "value", Object.class, true);
        List<Object> a2Values =
            AnnotationUtils.getElementValueArray(a2, "value", Object.class, true);
        HashSet<Object> newValues = new HashSet<Object>(a1Values.size() + a2Values.size());

        newValues.addAll(a1Values);
        newValues.addAll(a2Values);

        return createAnnotation(a1.getAnnotationType().toString(), newValues);
      }
      // Annotations are in this hierarchy, but they are not the same
      else {
        // If either is UNKNOWNVAL, ARRAYLEN, STRINGVAL, or BOOLEAN then
        // the LUB is
        // UnknownVal
        if (!(AnnotationUtils.areSameByClass(a1, IntVal.class)
            || AnnotationUtils.areSameByClass(a1, DoubleVal.class)
            || AnnotationUtils.areSameByClass(a2, IntVal.class)
            || AnnotationUtils.areSameByClass(a2, DoubleVal.class))) {
          return UNKNOWNVAL;
        } else {
          // At this point one of them must be a DoubleVal and one an
          // IntVal
          AnnotationMirror doubleAnno;
          AnnotationMirror intAnno;

          if (AnnotationUtils.areSameByClass(a2, DoubleVal.class)) {
            doubleAnno = a2;
            intAnno = a1;
          } else {
            doubleAnno = a1;
            intAnno = a2;
          }
          List<Long> intVals = getIntValues(intAnno);
          List<Double> doubleVals = getDoubleValues(doubleAnno);

          for (Long n : intVals) {
            doubleVals.add(n.doubleValue());
          }

          return createDoubleValAnnotation(doubleVals);
        }
      }
    }
 /**
  * Returns a set of pairs {@code (expr, annotation)} of preconditions according to the given
  * {@link RequiresQualifier}.
  */
 private Set<Pair<String, String>> getPrecondition(AnnotationMirror requiresAnnotation) {
   if (requiresAnnotation == null) {
     return Collections.emptySet();
   }
   Set<Pair<String, String>> result = new HashSet<>();
   List<String> expressions =
       AnnotationUtils.getElementValueArray(requiresAnnotation, "expression", String.class, false);
   String annotation =
       AnnotationUtils.getElementValueClassName(requiresAnnotation, "qualifier", false).toString();
   for (String expr : expressions) {
     result.add(Pair.of(expr, annotation));
   }
   return result;
 }
예제 #6
0
 @Override
 public Void visitNewClass(NewClassTree node, Void p) {
   AnnotatedDeclaredType type = atypeFactory.getAnnotatedType(node);
   ExpressionTree identifier = node.getIdentifier();
   if (identifier instanceof AnnotatedTypeTree) {
     AnnotatedTypeTree t = (AnnotatedTypeTree) identifier;
     for (AnnotationMirror a : atypeFactory.getAnnotatedType(t).getAnnotations()) {
       // is this an annotation of the nullness checker?
       boolean nullnessCheckerAnno =
           containsSameIgnoringValues(atypeFactory.getNullnessAnnotations(), a);
       if (nullnessCheckerAnno && !AnnotationUtils.areSame(NONNULL, a)) {
         // The type is not non-null => warning
         checker.report(Result.warning("new.class.type.invalid", type.getAnnotations()), node);
         // Note that other consistency checks are made by isValid.
       }
     }
     if (t.toString().contains("@PolyNull")) {
       // TODO: this is a hack, but PolyNull gets substituted
       // afterwards
       checker.report(Result.warning("new.class.type.invalid", type.getAnnotations()), node);
     }
   }
   // TODO: It might be nicer to introduce a framework-level
   // isValidNewClassType or some such.
   return super.visitNewClass(node, p);
 }
예제 #7
0
  /** @return the String value of a KeyFor, this will throw an exception */
  private Set<String> getKeys(final AnnotationMirror keyFor) {
    if (keyFor.getElementValues().size() == 0) {
      return new LinkedHashSet<>();
    }

    return new LinkedHashSet<>(
        AnnotationUtils.getElementValueArray(keyFor, "value", String.class, true));
  }
  @Override
  public Void visitWildcard(AnnotatedWildcardType type, Tree tree) {
    if (visitedNodes.containsKey(type)) {
      return visitedNodes.get(type);
    }

    // Keep in sync with visitTypeVariable
    Set<AnnotationMirror> onVar = type.getAnnotations();
    if (!onVar.isEmpty()) {
      // System.out.printf("BaseTypeVisitor.TypeValidator.visitWildcard(type: %s, tree: %s)",
      // type, tree);

      // TODO: the following check should not be necessary, once we are
      // able to
      // recurse on type parameters in AnnotatedTypes.isValidType (see
      // todo there).
      {
        // Check whether multiple qualifiers from the same hierarchy
        // appear.
        Set<AnnotationMirror> seenTops = AnnotationUtils.createAnnotationSet();
        for (AnnotationMirror aOnVar : onVar) {
          AnnotationMirror top = atypeFactory.getQualifierHierarchy().getTopAnnotation(aOnVar);
          if (seenTops.contains(top)) {
            this.reportError(type, tree);
          }
          seenTops.add(top);
        }
      }

      /* TODO: see note with visitTypeVariable
      if (type.getExtendsBoundField() != null) {
          AnnotatedTypeMirror upper = type.getExtendsBoundField();
          for (AnnotationMirror aOnVar : onVar) {
              if (upper.isAnnotatedInHierarchy(aOnVar) &&
                      !atypeFactory.getQualifierHierarchy().isSubtype(aOnVar,
                              upper.getAnnotationInHierarchy(aOnVar))) {
                  this.reportError(type, tree);
              }
          }
          upper.replaceAnnotations(onVar);
      }
      */

      if (type.getSuperBoundField() != null) {
        AnnotatedTypeMirror lower = type.getSuperBoundField();
        for (AnnotationMirror aOnVar : onVar) {
          if (lower.isAnnotatedInHierarchy(aOnVar)
              && !atypeFactory
                  .getQualifierHierarchy()
                  .isSubtype(lower.getAnnotationInHierarchy(aOnVar), aOnVar)) {
            this.reportError(type, tree);
          }
        }
        lower.replaceAnnotations(onVar);
      }
    }
    return super.visitWildcard(type, tree);
  }
  public InitializationAnnotatedTypeFactory(BaseTypeChecker checker, boolean useFbc) {
    super(checker, true);

    this.useFbc = useFbc;

    Set<Class<? extends Annotation>> tempInitAnnos = new LinkedHashSet<>();

    if (useFbc) {
      COMMITTED = AnnotationUtils.fromClass(elements, Initialized.class);
      FREE = AnnotationUtils.fromClass(elements, UnderInitialization.class);
      NOT_ONLY_COMMITTED = AnnotationUtils.fromClass(elements, NotOnlyInitialized.class);
      FBCBOTTOM = AnnotationUtils.fromClass(elements, FBCBottom.class);
      UNCLASSIFIED = AnnotationUtils.fromClass(elements, UnknownInitialization.class);

      tempInitAnnos.add(UnderInitialization.class);
      tempInitAnnos.add(Initialized.class);
      tempInitAnnos.add(UnknownInitialization.class);
      tempInitAnnos.add(FBCBottom.class);
    } else {
      COMMITTED = AnnotationUtils.fromClass(elements, NonRaw.class);
      FBCBOTTOM = COMMITTED; // @NonRaw is also bottom
      UNCLASSIFIED = AnnotationUtils.fromClass(elements, Raw.class);
      FREE = null; // unused
      NOT_ONLY_COMMITTED = null; // unused

      tempInitAnnos.add(Raw.class);
      tempInitAnnos.add(NonRaw.class);
    }

    initAnnos = Collections.unmodifiableSet(tempInitAnnos);
  }
예제 #10
0
 private boolean containsSameIgnoringValues(
     Set<Class<? extends Annotation>> quals, AnnotationMirror anno) {
   for (Class<? extends Annotation> q : quals) {
     if (AnnotationUtils.areSameByClass(anno, q)) {
       return true;
     }
   }
   return false;
 }
  /**
   * 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);
      }
    }
  }
  /** @inheritDoc */
  @Override
  public Slot getSlot(final AnnotationMirror annotationMirror) {

    final int id;
    if (InferenceQualifierHierarchy.isVarAnnot(annotationMirror)) {
      if (annotationMirror.getElementValues().isEmpty()) {
        return null; // TODO: should we instead throw an exception?
      } else {
        final AnnotationValue annoValue =
            annotationMirror.getElementValues().values().iterator().next();
        id = Integer.valueOf(annoValue.toString());
      }

      return getVariable(id);

    } else {

      if (constantStore != null) {
        return constantStore.get(AnnotationUtils.annotationName(annotationMirror));

      } else {
        for (Class<? extends Annotation> realAnno : realQualifiers) {
          if (AnnotationUtils.areSameByClass(annotationMirror, realAnno)) {
            return new ConstantSlot(annotationMirror, nextId());
          }
        }
      }
    }

    if (InferenceMain.isHackMode()) {
      return new ConstantSlot(
          InferenceMain.getInstance()
              .getRealTypeFactory()
              .getQualifierHierarchy()
              .getTopAnnotations()
              .iterator()
              .next(),
          nextId());
    }
    ErrorReporter.errorAbort(
        annotationMirror + " is a type of AnnotationMirror not handled by getVariableSlot.");
    return null; // Dead
  }
예제 #13
0
 /**
  * Returns a set of triples {@code (expr, (result, annotation))} of conditional postconditions
  * according to the given {@link EnsuresQualifierIf}.
  */
 private Set<Pair<String, Pair<Boolean, String>>> getConditionalPostcondition(
     AnnotationMirror ensuresAnnotationIf) {
   if (ensuresAnnotationIf == null) {
     return Collections.emptySet();
   }
   Set<Pair<String, Pair<Boolean, String>>> result = new HashSet<>();
   List<String> expressions =
       AnnotationUtils.getElementValueArray(
           ensuresAnnotationIf, "expression", String.class, false);
   String annotation =
       AnnotationUtils.getElementValueClassName(ensuresAnnotationIf, "qualifier", false)
           .toString();
   boolean annoResult =
       AnnotationUtils.getElementValue(ensuresAnnotationIf, "result", Boolean.class, false);
   for (String expr : expressions) {
     result.add(Pair.of(expr, Pair.of(annoResult, annotation)));
   }
   return result;
 }
    /**
     * If any constant-value annotation has &gt; 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);
        }
      }
    }
 private void getSubSupertypeFor2() {
   int num = 1;
   for (AnnotationMirror i : allTypes) {
     Set<AnnotationMirror> subtypeSet = new HashSet<AnnotationMirror>();
     Set<AnnotationMirror> supertypeSet = new HashSet<AnnotationMirror>();
     if (AnnotationUtils.areSame(i, this.top)) {
       subtypeSet.add(this.top);
       subtypeSet.add(this.bottom);
       supertypeSet.add(this.top);
     } else if (AnnotationUtils.areSame(i, this.bottom)) {
       subtypeSet.add(this.bottom);
       supertypeSet.add(this.bottom);
       supertypeSet.add(this.top);
     }
     this.subType.put(i, subtypeSet);
     this.superType.put(i, supertypeSet);
     this.modifierInt.put(i, num);
     this.IntModifier.put(num, i);
     num++;
   }
 }
 public static List<Character> getCharValues(AnnotationMirror intAnno) {
   if (intAnno != null) {
     List<Long> intValues =
         AnnotationUtils.getElementValueArray(intAnno, "value", Long.class, true);
     List<Character> charValues = new ArrayList<Character>();
     for (Long i : intValues) {
       charValues.add((char) i.intValue());
     }
     return charValues;
   }
   return new ArrayList<>();
 }
예제 #17
0
  /**
   * Returns a set of triples {@code (expr, (result, annotation))} of conditional postconditions on
   * the method {@code methodElement}.
   */
  public Set<Pair<String, Pair<Boolean, String>>> getConditionalPostconditions(
      ExecutableElement methodElement) {
    Set<Pair<String, Pair<Boolean, String>>> result = new HashSet<>();
    // Check for a single contract.
    AnnotationMirror ensuresAnnotationIf =
        factory.getDeclAnnotation(methodElement, EnsuresQualifierIf.class);
    result.addAll(getConditionalPostcondition(ensuresAnnotationIf));

    // Check for multiple contracts.
    AnnotationMirror ensuresAnnotationsIf =
        factory.getDeclAnnotation(methodElement, EnsuresQualifiersIf.class);
    if (ensuresAnnotationsIf != null) {
      List<AnnotationMirror> annotations =
          AnnotationUtils.getElementValueArray(
              ensuresAnnotationsIf, "value", AnnotationMirror.class, false);
      for (AnnotationMirror a : annotations) {
        result.addAll(getConditionalPostcondition(a));
      }
    }

    // Check type-system specific annotations.
    Class<ConditionalPostconditionAnnotation> metaAnnotation =
        ConditionalPostconditionAnnotation.class;
    List<Pair<AnnotationMirror, AnnotationMirror>> declAnnotations =
        factory.getDeclAnnotationWithMetaAnnotation(methodElement, metaAnnotation);
    for (Pair<AnnotationMirror, AnnotationMirror> r : declAnnotations) {
      AnnotationMirror anno = r.first;
      AnnotationMirror metaAnno = r.second;
      List<String> expressions =
          AnnotationUtils.getElementValueArray(anno, "expression", String.class, false);
      String annotationString =
          AnnotationUtils.getElementValueClassName(metaAnno, "qualifier", false).toString();
      boolean annoResult = AnnotationUtils.getElementValue(anno, "result", Boolean.class, false);
      for (String expr : expressions) {
        result.add(Pair.of(expr, Pair.of(annoResult, annotationString)));
      }
    }
    return result;
  }
예제 #18
0
  /**
   * Returns a set of pairs {@code (expr, annotation)} of preconditions on the element {@code
   * element}.
   */
  public Set<Pair<String, String>> getPreconditions(Element element) {
    Set<Pair<String, String>> result = new HashSet<>();
    // Check for a single contract.
    AnnotationMirror requiresAnnotation =
        factory.getDeclAnnotation(element, RequiresQualifier.class);
    result.addAll(getPrecondition(requiresAnnotation));

    // Check for multiple contracts.
    AnnotationMirror requiresAnnotations =
        factory.getDeclAnnotation(element, RequiresQualifiers.class);
    if (requiresAnnotations != null) {
      List<AnnotationMirror> annotations =
          AnnotationUtils.getElementValueArray(
              requiresAnnotations, "value", AnnotationMirror.class, false);
      for (AnnotationMirror a : annotations) {
        result.addAll(getPrecondition(a));
      }
    }

    // Check type-system specific annotations.
    Class<PreconditionAnnotation> metaAnnotation = PreconditionAnnotation.class;
    List<Pair<AnnotationMirror, AnnotationMirror>> declAnnotations =
        factory.getDeclAnnotationWithMetaAnnotation(element, metaAnnotation);
    for (Pair<AnnotationMirror, AnnotationMirror> r : declAnnotations) {
      AnnotationMirror anno = r.first;
      AnnotationMirror metaAnno = r.second;
      List<String> expressions =
          AnnotationUtils.getElementValueArray(anno, "value", String.class, false);
      String annotationString =
          AnnotationUtils.getElementValueClassName(metaAnno, "qualifier", false).toString();
      for (String expr : expressions) {
        result.add(Pair.of(expr, annotationString));
      }
    }
    return result;
  }
    /**
     * Subtype testing for initialization annotations. Will return false if either qualifier is not
     * an initialization annotation. Subclasses should override isSubtype and call this method for
     * initialization qualifiers.
     */
    public boolean isSubtypeInitialization(AnnotationMirror rhs, AnnotationMirror lhs) {
      if (!isInitializationAnnotation(rhs) || !isInitializationAnnotation(lhs)) {
        return false;
      }

      // 't' is always a subtype of 't'
      if (AnnotationUtils.areSame(rhs, lhs)) {
        return true;
      }
      // @Initialized is only a supertype of @FBCBottom.
      if (isCommitted(lhs)) {
        return isFbcBottom(rhs);
      }

      // @FBCBottom is a supertype of nothing.
      if (isFbcBottom(lhs)) {
        return false;
      }
      // @FBCBottom is a subtype of everything.
      if (isFbcBottom(rhs)) {
        return true;
      }
      boolean unc1 = isUnclassified(rhs);
      boolean unc2 = isUnclassified(lhs);
      boolean free1 = isFree(rhs);
      boolean free2 = isFree(lhs);

      // @Initialized is only a subtype of @UnknownInitialization.
      if (isCommitted(rhs)) {
        return unc2;
      }
      // @UnknownInitialization is not a subtype of @UnderInitialization.
      if (unc1 && free2) {
        return false;
      }
      // Now, either both annotations are @UnderInitialization, both annotations are
      // @UnknownInitialization or anno1 is @UnderInitialization and anno2 is
      // @UnknownInitialization.
      assert (free1 && free2) || (unc1 && unc2) || (free1 && unc2);
      // Thus, we only need to look at the type frame.
      TypeMirror frame1 = getTypeFrameFromAnnotation(rhs);
      TypeMirror frame2 = getTypeFrameFromAnnotation(lhs);
      return types.isSubtype(frame1, frame2);
    }
    @Override
    public String formatAnnotationString(
        Collection<? extends AnnotationMirror> annos, boolean printInvisible) {
      // create an empty annotation set
      Set<AnnotationMirror> trimmedAnnoSet = AnnotationUtils.createAnnotationSet();

      // loop through all the annotation mirrors to see if they use Prefix.one, remove Prefix.one if
      // it does
      for (AnnotationMirror anno : annos) {
        if (UnitsRelationsTools.getPrefix(anno) == Prefix.one) {
          anno = UnitsRelationsTools.removePrefix(elements, anno);
        }
        // add to set
        trimmedAnnoSet.add(anno);
      }

      return super.formatAnnotationString(
          Collections.unmodifiableSet(trimmedAnnoSet), printInvisible);
    }
 public static List<Boolean> getBooleanValues(AnnotationMirror boolAnno) {
   if (boolAnno != null) {
     List<Boolean> boolValues =
         AnnotationUtils.getElementValueArray(boolAnno, "value", Boolean.class, true);
     Set<Boolean> boolSet = new TreeSet<>(boolValues);
     if (boolSet.size() > 1) {
       // boolSet={true,false};
       return new ArrayList<>();
     }
     if (boolSet.size() == 0) {
       // boolSet={};
       return new ArrayList<>();
     }
     if (boolSet.size() == 1) {
       // boolSet={true} or boolSet={false}
       return new ArrayList<>(boolSet);
     }
   }
   return new ArrayList<>();
 }
    /**
     * Recursive method to handle array initializations. Recursively descends the initializer to
     * find each dimension's size and create the appropriate annotation for it.
     *
     * @param dimensions a list of ExpressionTrees where each ExpressionTree is a specifier of the
     *     size of that dimension (should be an IntVal).
     * @param type the AnnotatedTypeMirror of the array
     */
    private void handleDimensions(
        List<? extends ExpressionTree> dimensions, AnnotatedArrayType type) {
      if (dimensions.size() > 1) {
        handleDimensions(
            dimensions.subList(1, dimensions.size()), (AnnotatedArrayType) type.getComponentType());
      }

      AnnotationMirror dimType =
          getAnnotatedType(dimensions.get(0)).getAnnotationInHierarchy(UNKNOWNVAL);
      if (!AnnotationUtils.areSameIgnoringValues(dimType, UNKNOWNVAL)) {
        List<Long> longLengths = getIntValues(dimType);

        HashSet<Integer> lengths = new HashSet<Integer>(longLengths.size());
        for (Long l : longLengths) {
          lengths.add(l.intValue());
        }
        AnnotationMirror newQual = createArrayLenAnnotation(new ArrayList<>(lengths));
        type.replaceAnnotation(newQual);
      }
    }
  /** Returns whether the field {@code f} is unused, given the annotations on the receiver. */
  private boolean isUnused(
      VariableTree field, Collection<? extends AnnotationMirror> receiverAnnos) {
    if (receiverAnnos.isEmpty()) {
      return false;
    }

    AnnotationMirror unused =
        getDeclAnnotation(TreeUtils.elementFromDeclaration(field), Unused.class);
    if (unused == null) {
      return false;
    }

    Name when = AnnotationUtils.getElementValueClassName(unused, "when", false);
    for (AnnotationMirror anno : receiverAnnos) {
      Name annoName = ((TypeElement) anno.getAnnotationType().asElement()).getQualifiedName();
      if (annoName.contentEquals(when)) {
        return true;
      }
    }

    return false;
  }
 public static List<Integer> getArrayLength(AnnotationMirror arrayAnno) {
   return AnnotationUtils.getElementValueArray(arrayAnno, "value", Integer.class, true);
 }
 public static List<Double> getDoubleValues(AnnotationMirror doubleAnno) {
   return AnnotationUtils.getElementValueArray(doubleAnno, "value", Double.class, true);
 }
 public static List<Long> getIntValues(AnnotationMirror intAnno) {
   return AnnotationUtils.getElementValueArray(intAnno, "value", Long.class, true);
 }
 /**
  * Is {@code anno} the {@link Initialized} annotation? If {@code useFbc} is false, then {@link
  * NonRaw} is used in the comparison.
  */
 public boolean isCommitted(AnnotationMirror anno) {
   return AnnotationUtils.areSame(anno, COMMITTED);
 }
    /**
     * Computes subtyping as per the subtyping in the qualifier hierarchy structure unless both
     * annotations are Value. In this case, rhs is a subtype of lhs iff lhs contains at least every
     * element of rhs
     *
     * @return true if rhs is a subtype of lhs, false otherwise
     */
    @Override
    public boolean isSubtype(AnnotationMirror rhs, AnnotationMirror lhs) {

      if (AnnotationUtils.areSameByClass(lhs, UnknownVal.class)
          || AnnotationUtils.areSameByClass(rhs, BottomVal.class)) {
        return true;
      } else if (AnnotationUtils.areSameByClass(rhs, UnknownVal.class)
          || AnnotationUtils.areSameByClass(lhs, BottomVal.class)) {
        return false;
      } else if (AnnotationUtils.areSameIgnoringValues(lhs, rhs)) {
        // Same type, so might be subtype
        List<Object> lhsValues =
            AnnotationUtils.getElementValueArray(lhs, "value", Object.class, true);
        List<Object> rhsValues =
            AnnotationUtils.getElementValueArray(rhs, "value", Object.class, true);
        return lhsValues.containsAll(rhsValues);
      } else if (AnnotationUtils.areSameByClass(lhs, DoubleVal.class)
          && AnnotationUtils.areSameByClass(rhs, IntVal.class)) {
        List<Long> rhsValues;
        rhsValues = AnnotationUtils.getElementValueArray(rhs, "value", Long.class, true);
        List<Double> lhsValues =
            AnnotationUtils.getElementValueArray(lhs, "value", Double.class, true);
        boolean same = false;
        for (Long rhsLong : rhsValues) {
          for (Double lhsDbl : lhsValues) {
            if (lhsDbl.doubleValue() == rhsLong.doubleValue()) {
              same = true;
              break;
            }
          }
          if (!same) {
            return false;
          }
        }
        return same;
      }
      return false;
    }
// JLTODO: document!
// It's not nice that so many fields are public and non-final.
public class LatticeGenerator {

  public ProcessingEnvironment processingEnv;
  public QualifierHierarchy qualHierarchy;
  public Map<AnnotationMirror, Collection<AnnotationMirror>> subType =
      AnnotationUtils.createAnnotationMap();
  public Map<AnnotationMirror, Collection<AnnotationMirror>> superType =
      AnnotationUtils.createAnnotationMap();
  public Map<AnnotationMirror, Collection<AnnotationMirror>> notComparableType =
      AnnotationUtils.createAnnotationMap();
  public Map<AnnotationMirror, Integer> modifierInt = AnnotationUtils.createAnnotationMap();
  public Map<Integer, AnnotationMirror> IntModifier = new HashMap<Integer, AnnotationMirror>();
  public Set<? extends AnnotationMirror> allTypes;
  public AnnotationMirror top;
  public AnnotationMirror bottom;
  public int numModifiers;

  public LatticeGenerator(QualifierHierarchy qualHierarchy) {
    this.qualHierarchy = qualHierarchy;
    this.allTypes = qualHierarchy.getTypeQualifiers();
    this.top = qualHierarchy.getTopAnnotations().iterator().next();
    this.bottom = qualHierarchy.getBottomAnnotations().iterator().next();
    this.numModifiers = qualHierarchy.getTypeQualifiers().size();
    getSubSupertype();
    getNotComparable();
    //        for (AnnotationMirror i : subType.keySet()){
    //            System.out.println("Key: " + i.toString() + "   Value: "+
    // subType.get(i).toString());
    //        }
    // System.out.println(allTypes.toString());

  }

  public LatticeGenerator(
      AnnotationMirror dataflowAnnotation, ProcessingEnvironment processingEnv) {
    this.processingEnv = processingEnv;
    this.top = dataflowAnnotation;
    this.bottom =
        DataflowUtils.createDataflowAnnotation(
            new HashSet<String>(Arrays.asList("")), processingEnv);
    this.numModifiers = 2;
    addAlltypesFor2();
    getSubSupertypeFor2();
    // TODO:
  }

  private void addAlltypesFor2() {
    Set<AnnotationMirror> all2Types = new HashSet<AnnotationMirror>();
    all2Types.add(this.top);
    all2Types.add(this.bottom);
    this.allTypes = all2Types;
  }

  private void getSubSupertypeFor2() {
    int num = 1;
    for (AnnotationMirror i : allTypes) {
      Set<AnnotationMirror> subtypeSet = new HashSet<AnnotationMirror>();
      Set<AnnotationMirror> supertypeSet = new HashSet<AnnotationMirror>();
      if (AnnotationUtils.areSame(i, this.top)) {
        subtypeSet.add(this.top);
        subtypeSet.add(this.bottom);
        supertypeSet.add(this.top);
      } else if (AnnotationUtils.areSame(i, this.bottom)) {
        subtypeSet.add(this.bottom);
        supertypeSet.add(this.bottom);
        supertypeSet.add(this.top);
      }
      this.subType.put(i, subtypeSet);
      this.superType.put(i, supertypeSet);
      this.modifierInt.put(i, num);
      this.IntModifier.put(num, i);
      num++;
    }
  }

  private void getSubSupertype() {
    int num = 1;
    for (AnnotationMirror i : allTypes) {
      Set<AnnotationMirror> subtypeFori = new HashSet<AnnotationMirror>();
      Set<AnnotationMirror> supertypeFori = new HashSet<AnnotationMirror>();
      for (AnnotationMirror j : allTypes) {
        if (qualHierarchy.isSubtype(j, i)) {
          subtypeFori.add(j);
        }
        if (qualHierarchy.isSubtype(i, j)) {
          supertypeFori.add(j);
        }
      }
      subType.put(i, subtypeFori);
      superType.put(i, supertypeFori);
      modifierInt.put(i, num);
      IntModifier.put(num, i);
      num++;
    }
    //        for (Integer j: IntModifier.keySet()){
    //            System.out.println("final key "+j+ "  " + "final value: " +
    // IntModifier.get(j).toString());
    //        }
  }

  private void getNotComparable() {
    for (AnnotationMirror i : allTypes) {
      Set<AnnotationMirror> notComparableFori = new HashSet<AnnotationMirror>();
      for (AnnotationMirror j : allTypes) {
        if (!subType.get(i).contains(j) && !subType.get(j).contains(i)) {
          notComparableFori.add(j);
        }
      }
      if (!notComparableFori.isEmpty()) {
        notComparableType.put(i, notComparableFori);
      }
    }
  }
}
 public I18nTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
   super(atypeFactory);
   LOCALIZED = AnnotationUtils.fromClass(elements, Localized.class);
 }