public StringConcatenateNode(Tree tree, Node left, Node right) {
   super(InternalUtils.typeOf(tree));
   assert tree.getKind() == Kind.PLUS;
   this.tree = tree;
   this.left = left;
   this.right = right;
 }
    /** Returns the least upper bound of two types. */
    protected TypeMirror lubTypeFrame(TypeMirror a, TypeMirror b) {
      if (types.isSubtype(a, b)) {
        return b;
      } else if (types.isSubtype(b, a)) {
        return a;
      }

      return InternalUtils.leastUpperBound(processingEnv, a, b);
    }
 public LocalVariableNode(Tree t) {
   super(InternalUtils.typeOf(t));
   // IdentifierTree for normal uses of the local variable or parameter,
   // and VariableTree for the translation of an initializer block
   assert t != null;
   assert t instanceof IdentifierTree || t instanceof VariableTree;
   tree = t;
   this.receiver = null;
 }
    @Override
    public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) {
      if (TreeUtils.isFieldAccess(tree) && isUnderlyingTypeAValue(type)) {
        VariableElement elem = (VariableElement) InternalUtils.symbol(tree);
        Object value = elem.getConstantValue();
        if (value != null) {
          // compile time constant
          type.replaceAnnotation(
              resultAnnotationHandler(
                  type.getUnderlyingType(), Collections.singletonList(value), tree));
          return null;
        }
        if (ElementUtils.isStatic(elem) && ElementUtils.isFinal(elem)) {
          Element e = InternalUtils.symbol(tree.getExpression());
          if (e != null) {
            String classname = ElementUtils.getQualifiedClassName(e).toString();
            String fieldName = tree.getIdentifier().toString();
            value = evalutator.evaluateStaticFieldAccess(classname, fieldName, tree);
            if (value != null)
              type.replaceAnnotation(
                  resultAnnotationHandler(
                      type.getUnderlyingType(), Collections.singletonList(value), tree));
            return null;
          }
        }

        if (tree.getIdentifier().toString().equals("length")) {
          AnnotatedTypeMirror receiverType = getAnnotatedType(tree.getExpression());
          if (receiverType.getKind() == TypeKind.ARRAY) {
            AnnotationMirror arrayAnno = receiverType.getAnnotation(ArrayLen.class);
            if (arrayAnno != null) {
              // array.length, where array : @ArrayLen(x)
              List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno);
              type.replaceAnnotation(createNumberAnnotationMirror(new ArrayList<Number>(lengths)));
              return null;
            }
          }
        }
      }
      return null;
    }
  @Override
  public boolean isValidUse(
      AnnotatedDeclaredType declarationType, AnnotatedDeclaredType useType, Tree tree) {
    // At most a single qualifier on a type, ignoring a possible PolyAll
    // annotation.
    boolean foundInit = false;
    boolean foundNonNull = false;
    Set<Class<? extends Annotation>> initQuals = atypeFactory.getInitializationAnnotations();
    Set<Class<? extends Annotation>> nonNullQuals = atypeFactory.getNullnessAnnotations();

    for (AnnotationMirror anno : useType.getAnnotations()) {
      if (QualifierPolymorphism.isPolyAll(anno)) {
        // ok.
      } else if (containsSameIgnoringValues(initQuals, anno)) {
        if (foundInit) {
          return false;
        }
        foundInit = true;
      } else if (containsSameIgnoringValues(nonNullQuals, anno)) {
        if (foundNonNull) {
          return false;
        }
        foundNonNull = true;
      }
    }

    if (tree.getKind() == Tree.Kind.VARIABLE) {
      Element vs = InternalUtils.symbol(tree);
      switch (vs.getKind()) {
        case EXCEPTION_PARAMETER:
          if (useType.hasAnnotation(NULLABLE)) {
            // Exception parameters cannot use Nullable
            // annotations. They default to NonNull.
            return false;
          }
          break;
        default:
          // nothing to do
          break;
      }
    }

    // The super implementation checks that useType is a subtype
    // of declarationType. However, declarationType by default
    // is NonNull, which would then forbid Nullable uses.
    // Therefore, don't perform this check.
    return true;
  }
 /** @return true if the type of the tree is a primitive */
 private static final boolean isPrimitive(ExpressionTree tree) {
   return InternalUtils.typeOf(tree).getKind().isPrimitive();
 }
 /** @return true if the type of the tree is a super of String */
 private final boolean isString(ExpressionTree tree) {
   TypeMirror type = InternalUtils.typeOf(tree);
   return types.isAssignable(stringType, type);
 }
  // Handles the -Acheckclass command-line argument
  private boolean shouldCheckFor(ExpressionTree tree) {
    if (typeToCheck == null) return true;

    TypeMirror type = InternalUtils.typeOf(tree);
    return types.isSubtype(type, typeToCheck) || types.isSubtype(typeToCheck, type);
  }