@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);
 }
  @Override
  public Void visitBinary(BinaryTree node, Void p) {

    // No checking unless the operator is "==" or "!=".
    if (!(node.getKind() == Tree.Kind.EQUAL_TO || node.getKind() == Tree.Kind.NOT_EQUAL_TO))
      return super.visitBinary(node, p);

    ExpressionTree leftOp = node.getLeftOperand();
    ExpressionTree rightOp = node.getRightOperand();

    // Check passes if either arg is null.
    if (leftOp.getKind() == Tree.Kind.NULL_LITERAL || rightOp.getKind() == Tree.Kind.NULL_LITERAL)
      return super.visitBinary(node, p);

    AnnotatedTypeMirror left = atypeFactory.getAnnotatedType(leftOp);
    AnnotatedTypeMirror right = atypeFactory.getAnnotatedType(rightOp);

    // If either argument is a primitive, check passes due to auto-unboxing
    if (left.getKind().isPrimitive() || right.getKind().isPrimitive())
      return super.visitBinary(node, p);

    if (!(shouldCheckFor(leftOp) && shouldCheckFor(rightOp))) return super.visitBinary(node, p);

    // Syntactic checks for legal uses of ==
    if (suppressInsideComparison(node)) return super.visitBinary(node, p);
    if (suppressEarlyEquals(node)) return super.visitBinary(node, p);
    if (suppressEarlyCompareTo(node)) return super.visitBinary(node, p);

    if (suppressClassAnnotation(left, right)) {
      return super.visitBinary(node, p);
    }

    Element leftElt = null;
    Element rightElt = null;
    if (left
        instanceof org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) {
      leftElt = ((DeclaredType) left.getUnderlyingType()).asElement();
    }
    if (right
        instanceof org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType) {
      rightElt = ((DeclaredType) right.getUnderlyingType()).asElement();
    }

    // if neither @Interned or @UsesObjectEquals, report error
    if (!(left.hasEffectiveAnnotation(INTERNED)
        || (leftElt != null && leftElt.getAnnotation(UsesObjectEquals.class) != null)))
      checker.report(Result.failure("not.interned", left), leftOp);
    if (!(right.hasEffectiveAnnotation(INTERNED)
        || (rightElt != null && rightElt.getAnnotation(UsesObjectEquals.class) != null)))
      checker.report(Result.failure("not.interned", right), rightOp);
    return super.visitBinary(node, p);
  }
 protected void reportValidityResult(
     final /*@CompilerMessageKey*/ String errorType,
     final AnnotatedTypeMirror type,
     final Tree p) {
   checker.report(Result.failure(errorType, type.getAnnotations(), type.toString()), p);
   isValid = false;
 }
 @Override
 public Void visitAnnotation(AnnotationTree node, Void p) {
   Element anno = TreeInfo.symbol((JCTree) node.getAnnotationType());
   if (anno.toString().equals(DefaultType.class.getName())) {
     checker.report(Result.failure("annotation.not.allowed.in.src", anno.toString()), node);
   }
   return super.visitAnnotation(node, p);
 }
  /**
   * Reports an error if a comparison of a @NonNull expression with the null literal is performed.
   */
  protected void checkForRedundantTests(BinaryTree node) {

    final ExpressionTree leftOp = node.getLeftOperand();
    final ExpressionTree rightOp = node.getRightOperand();

    // respect command-line option
    if (!checker.getLintOption(
        AbstractNullnessChecker.LINT_REDUNDANTNULLCOMPARISON,
        AbstractNullnessChecker.LINT_DEFAULT_REDUNDANTNULLCOMPARISON)) {
      return;
    }

    // equality tests
    if ((node.getKind() == Tree.Kind.EQUAL_TO || node.getKind() == Tree.Kind.NOT_EQUAL_TO)) {
      AnnotatedTypeMirror left = atypeFactory.getAnnotatedType(leftOp);
      AnnotatedTypeMirror right = atypeFactory.getAnnotatedType(rightOp);
      if (leftOp.getKind() == Tree.Kind.NULL_LITERAL && right.hasEffectiveAnnotation(NONNULL))
        checker.report(Result.warning(KNOWN_NONNULL, rightOp.toString()), node);
      else if (rightOp.getKind() == Tree.Kind.NULL_LITERAL && left.hasEffectiveAnnotation(NONNULL))
        checker.report(Result.warning(KNOWN_NONNULL, leftOp.toString()), node);
    }
  }
  /*
   * Method to implement the @UsesObjectEquals functionality.
   * If a class is marked @UsesObjectEquals, it must:
   *
   *    -not override .equals(Object)
   *    -be a subclass of Object or another class marked @UsesObjectEquals
   *
   * If a class is not marked @UsesObjectEquals, it must:
   *
   * 	  -not have a superclass marked @UsesObjectEquals
   *
   *
   * @see org.checkerframework.common.basetype.BaseTypeVisitor#visitClass(com.sun.source.tree.ClassTree, java.lang.Object)
   */
  @Override
  public Void visitClass(ClassTree node, Void p) {
    // Looking for an @UsesObjectEquals class declaration

    TypeElement elt = TreeUtils.elementFromDeclaration(node);
    UsesObjectEquals annotation = elt.getAnnotation(UsesObjectEquals.class);

    Tree superClass = node.getExtendsClause();
    Element elmt = null;
    if (superClass != null
        && (superClass instanceof IdentifierTree || superClass instanceof MemberSelectTree)) {
      elmt = TreeUtils.elementFromUse((ExpressionTree) superClass);
    }

    // if it's there, check to make sure does not override equals
    // and supertype is Object or @UsesObjectEquals
    if (annotation != null) {
      // check methods to ensure no .equals
      if (overridesEquals(node)) {
        checker.report(Result.failure("overrides.equals"), node);
      }

      if (!(superClass == null
          || (elmt != null && elmt.getAnnotation(UsesObjectEquals.class) != null))) {
        checker.report(Result.failure("superclass.unmarked"), node);
      }
    } else {
      // the class is not marked @UsesObjectEquals -> make sure its superclass isn't either.
      // this is impossible after design change making @UsesObjectEquals inherited?
      // check left in case of future design change back to non-inherited.
      if (superClass != null
          && (elmt != null && elmt.getAnnotation(UsesObjectEquals.class) != null)) {
        checker.report(Result.failure("superclass.marked"), node);
      }
    }

    return super.visitClass(node, p);
  }
  @Override
  public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    if (isInvocationOfEquals(node)) {
      AnnotatedTypeMirror recv = atypeFactory.getReceiverType(node);
      AnnotatedTypeMirror comp = atypeFactory.getAnnotatedType(node.getArguments().get(0));

      if (this.checker.getLintOption("dotequals", true)
          && recv.hasEffectiveAnnotation(INTERNED)
          && comp.hasEffectiveAnnotation(INTERNED))
        checker.report(Result.warning("unnecessary.equals"), node);
    }

    return super.visitMethodInvocation(node, p);
  }
  @Override
  public Void visitNewArray(NewArrayTree node, Void p) {
    AnnotatedArrayType type = atypeFactory.getAnnotatedType(node);
    AnnotatedTypeMirror componentType = type.getComponentType();
    if (componentType.hasEffectiveAnnotation(NONNULL)
        && !isNewArrayAllZeroDims(node)
        && !isNewArrayInToArray(node)
        && !TypesUtils.isPrimitive(componentType.getUnderlyingType())
        && checker.getLintOption("forbidnonnullarraycomponents", false)) {
      checker.report(
          Result.failure("new.array.type.invalid", componentType.getAnnotations(), type.toString()),
          node);
    }

    return super.visitNewArray(node, p);
  }
 /**
  * Issues a 'dereference.of.nullable' if the type is not of a {@link NonNull} type.
  *
  * @param tree the tree where the error is to reported
  * @param errMsg the error message (must be {@link CompilerMessageKey})
  */
 private void checkForNullability(ExpressionTree tree, /*@CompilerMessageKey*/ String errMsg) {
   AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(tree);
   if (!type.hasEffectiveAnnotation(NONNULL)) {
     checker.report(Result.failure(errMsg, tree), tree);
   }
 }