package org.checkerframework.checker.interning;

import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.IfTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Scope;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.checker.interning.qual.CompareToMethod;
import org.checkerframework.checker.interning.qual.EqualsMethod;
import org.checkerframework.checker.interning.qual.InternMethod;
import org.checkerframework.checker.interning.qual.Interned;
import org.checkerframework.checker.interning.qual.InternedDistinct;
import org.checkerframework.checker.interning.qual.UsesObjectEquals;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.framework.type.AnnotatedTypeFactory.ParameterizedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.util.Heuristics;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;

/**
 * Typechecks source code for interning violations. A type is considered interned if its primary
 * annotation is {@link Interned} or {@link InternedDistinct}. This visitor reports errors or
 * warnings for violations for the following cases:
 *
 * <ol>
 *   <li value="1">either argument to a "==" or "!=" comparison is not Interned (error
 *       "not.interned"). As a special case, the comparison is permitted if either arugment is
 *       InternedDistinct.
 *   <li value="2">the receiver and argument for a call to an equals method are both Interned
 *       (optional warning "unnecessary.equals")
 * </ol>
 *
 * @see BaseTypeVisitor
 */
public final class InterningVisitor extends BaseTypeVisitor<InterningAnnotatedTypeFactory> {

  /** The @Interned annotation. */
  private final AnnotationMirror INTERNED = AnnotationBuilder.fromClass(elements, Interned.class);
  /** The @InternedDistinct annotation. */
  private final AnnotationMirror INTERNED_DISTINCT =
      AnnotationBuilder.fromClass(elements, InternedDistinct.class);
  /**
   * The declared type of which the equality tests should be tested, if the user explicitly passed
   * one. The user can pass the class name via the {@code -Acheckclass=...} option. Null if no class
   * is specified, or the class specified isn't in the classpath.
   */
  private final DeclaredType typeToCheck = typeToCheck();

  /** The Comparable.compareTo method. */
  private final ExecutableElement comparableCompareTo =
      TreeUtils.getMethod(
          "java.lang.Comparable", "compareTo", 1, checker.getProcessingEnvironment());

  /** Create an InterningVisitor. */
  public InterningVisitor(BaseTypeChecker checker) {
    super(checker);
  }

  /**
   * @return true if interning should be verified for the input expression. By default, all classes
   *     are checked for interning unless {@code -Acheckclass} is specified.
   * @see <a href="https://checkerframework.org/manual/#interning-checks">What the Interning Checker
   *     checks</a>
   */
  private boolean shouldCheckExpression(ExpressionTree tree) {
    if (typeToCheck == null) {
      return true;
    }

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

  /** Checks comparison operators, == and !=, for INTERNING violations. */
  @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 (left.hasEffectiveAnnotation(INTERNED_DISTINCT)
        || right.hasEffectiveAnnotation(INTERNED_DISTINCT)) {
      return super.visitBinary(node, p);
    }

    // If shouldCheckExpression returns true for either the LHS or RHS,
    // this method proceeds with the interning check.

    // Justification: Consider the following scenario:

    // interface I { ... }
    // class A { ... }
    // class B extends A implements I { ... }
    // ...
    // I i;
    // A a;
    // ...
    // if (a == i) { ... }

    // The Java compiler does not issue a compilation error for the (a == i) comparison because,
    // even though A does not implement I, 'a' could be assigned an instance of B, and B does
    // implement I (note that the compiler does not need to know about the existence of B
    // in order to assume this).

    // Now suppose the user passes -AcheckClass=A on the command-line.
    // I is not a subtype or supertype of A, so shouldCheckExpression will not return true for I.
    // But the interning check must be performed, given the argument above.  Therefore if
    // shouldCheckExpression returns true for either the LHS or the RHS, this method proceeds
    // with the interning check.

    if (!shouldCheckExpression(leftOp) && !shouldCheckExpression(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 (suppressEqualsIfClassIsAnnotated(left, right)) {
      return super.visitBinary(node, p);
    }

    Element leftElt = TypesUtils.getTypeElement(left.getUnderlyingType());
    // If neither @Interned or @UsesObjectEquals, report error.
    if (!(left.hasEffectiveAnnotation(INTERNED)
        || (leftElt != null
            && atypeFactory.getDeclAnnotation(leftElt, UsesObjectEquals.class) != null))) {
      checker.reportError(leftOp, "not.interned", left);
    }

    Element rightElt = TypesUtils.getTypeElement(right.getUnderlyingType());
    if (!(right.hasEffectiveAnnotation(INTERNED)
        || (rightElt != null
            && atypeFactory.getDeclAnnotation(rightElt, UsesObjectEquals.class) != null))) {
      checker.reportError(rightOp, "not.interned", right);
    }
    return super.visitBinary(node, p);
  }

  /**
   * If lint option "dotequals" is specified, warn if the .equals method is used where reference
   * equality is safe.
   */
  @Override
  public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    if (isInvocationOfEquals(node)) {
      AnnotatedTypeMirror receiverType = atypeFactory.getReceiverType(node);
      AnnotatedTypeMirror comp = atypeFactory.getAnnotatedType(node.getArguments().get(0));

      if (this.checker.getLintOption("dotequals", true)
          && receiverType.hasEffectiveAnnotation(INTERNED)
          && comp.hasEffectiveAnnotation(INTERNED)) {
        checker.reportWarning(node, "unnecessary.equals");
      }
    }

    return super.visitMethodInvocation(node, p);
  }

  // Ensure that method annotations are not written on methods they don't apply to.
  @Override
  public Void visitMethod(MethodTree node, Void p) {
    ExecutableElement methElt = TreeUtils.elementFromDeclaration(node);
    boolean hasCompareToMethodAnno =
        atypeFactory.getDeclAnnotation(methElt, CompareToMethod.class) != null;
    boolean hasEqualsMethodAnno =
        atypeFactory.getDeclAnnotation(methElt, EqualsMethod.class) != null;
    boolean hasInternMethodAnno =
        atypeFactory.getDeclAnnotation(methElt, InternMethod.class) != null;
    int params = methElt.getParameters().size();
    if (hasCompareToMethodAnno && !(params == 1 || params == 2)) {
      checker.reportError(
          node, "invalid.method.annotation", "@CompareToMethod", "1 or 2", methElt, params);
    } else if (hasEqualsMethodAnno && !(params == 1 || params == 2)) {
      checker.reportError(
          node, "invalid.method.annotation", "@EqualsMethod", "1 or 2", methElt, params);
    } else if (hasInternMethodAnno && !(params == 0)) {
      checker.reportError(node, "invalid.method.annotation", "@InternMethod", "0", methElt, params);
    }

    return super.visitMethod(node, p);
  }

  /**
   * Method to implement the @UsesObjectEquals functionality. If a class is annotated
   * with @UsesObjectEquals, it must:
   *
   * <ul>
   *   <li>not override .equals(Object) and be a subclass of a class annotated
   *       with @UsesObjectEquals, or
   *   <li>override equals(Object) with body "this == arg"
   * </ul>
   *
   * If a class is not annotated with @UsesObjectEquals, it must:
   *
   * <ul>
   *   <li>not have a superclass annotated with @UsesObjectEquals
   * </ul>
   *
   * @see
   *     org.checkerframework.common.basetype.BaseTypeVisitor#visitClass(com.sun.source.tree.ClassTree,
   *     java.lang.Object)
   */
  @Override
  public void processClassTree(ClassTree classTree) {
    TypeElement elt = TreeUtils.elementFromDeclaration(classTree);
    AnnotationMirror annotation = atypeFactory.getDeclAnnotation(elt, UsesObjectEquals.class);

    // If @UsesObjectEquals is present, check to make sure the class does not override equals
    // and its supertype is Object or is annotated with @UsesObjectEquals.
    if (annotation != null) {
      MethodTree equalsMethod = equalsImplementation(classTree);
      if (equalsMethod != null) {
        if (!isReferenceEqualityImplementation(equalsMethod)) {
          checker.reportError(classTree, "overrides.equals");
        }
      } else {
        // Does not override equals()
        TypeMirror superClass = elt.getSuperclass();
        if (superClass != null
            // The super class of an interface is "none" rather than null.
            && superClass.getKind() == TypeKind.DECLARED) {
          TypeElement superClassElement = TypesUtils.getTypeElement(superClass);
          if (superClassElement != null
              && !ElementUtils.isObject(superClassElement)
              && atypeFactory.getDeclAnnotation(superClassElement, UsesObjectEquals.class)
                  == null) {
            checker.reportError(classTree, "superclass.notannotated");
          }
        }
      }
    }

    super.processClassTree(classTree);
  }

  /**
   * Returns true if the given equals() method implements reference equality.
   *
   * @param equalsMethod an overriding implementation of Object.equals()
   * @return true if the given equals() method implements reference equality
   */
  private boolean isReferenceEqualityImplementation(MethodTree equalsMethod) {
    BlockTree body = equalsMethod.getBody();
    List<? extends StatementTree> bodyStatements = body.getStatements();
    if (bodyStatements.size() == 1) {
      StatementTree bodyStatement = bodyStatements.get(0);
      if (bodyStatement.getKind() == Tree.Kind.RETURN) {
        ExpressionTree returnExpr =
            TreeUtils.withoutParens(((ReturnTree) bodyStatement).getExpression());
        if (returnExpr.getKind() == Tree.Kind.EQUAL_TO) {
          BinaryTree bt = (BinaryTree) returnExpr;
          ExpressionTree lhsTree = bt.getLeftOperand();
          ExpressionTree rhsTree = bt.getRightOperand();
          if (lhsTree.getKind() == Tree.Kind.IDENTIFIER
              && rhsTree.getKind() == Tree.Kind.IDENTIFIER) {
            Name leftName = ((IdentifierTree) lhsTree).getName();
            Name rightName = ((IdentifierTree) rhsTree).getName();
            Name paramName = equalsMethod.getParameters().get(0).getName();
            if ((leftName.contentEquals("this") && rightName == paramName)
                || (leftName == paramName && rightName.contentEquals("this"))) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  @Override
  protected void checkConstructorResult(
      AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {
    if (constructorElement.getEnclosingElement().getKind() == ElementKind.ENUM) {
      // Enums constructor are only called once per enum constant.
      return;
    }
    super.checkConstructorResult(constructorType, constructorElement);
  }

  @Override
  public boolean validateTypeOf(Tree tree) {
    // Don't check the result type of a constructor, because it must be @UnknownInterned, even
    // if the type on the class declaration is @Interned.
    if (tree.getKind() == Tree.Kind.METHOD && TreeUtils.isConstructor((MethodTree) tree)) {
      return true;
    } else if (tree.getKind() == Tree.Kind.NEW_CLASS) {
      NewClassTree newClassTree = (NewClassTree) tree;
      TypeMirror typeMirror = TreeUtils.typeOf(newClassTree);
      Set<AnnotationMirror> bounds = atypeFactory.getTypeDeclarationBounds(typeMirror);
      // Don't issue an invalid type warning for creations of objects of interned classes;
      // instead, issue an interned.object.creation if required.
      if (atypeFactory.containsSameByClass(bounds, Interned.class)) {
        ParameterizedExecutableType fromUse = atypeFactory.constructorFromUse(newClassTree);
        AnnotatedExecutableType constructor = fromUse.executableType;
        if (!checkCreationOfInternedObject(newClassTree, constructor)) {
          return false;
        }
      }
    }
    return super.validateTypeOf(tree);
  }

  /**
   * Issue an error if {@code newInternedObject} is not immediately interned.
   *
   * @param newInternedObject call to a constructor of an interned class
   * @param constructor declared type of the constructor
   * @return false unless {@code newInternedObject} is immediately interned
   */
  private boolean checkCreationOfInternedObject(
      NewClassTree newInternedObject, AnnotatedExecutableType constructor) {
    if (constructor.getReturnType().hasAnnotation(Interned.class)) {
      return true;
    }
    TreePath path = getCurrentPath();
    if (path != null) {
      TreePath parentPath = path.getParentPath();
      while (parentPath != null && parentPath.getLeaf().getKind() == Tree.Kind.PARENTHESIZED) {
        parentPath = parentPath.getParentPath();
      }
      if (parentPath != null && parentPath.getParentPath() != null) {
        Tree parent = parentPath.getParentPath().getLeaf();
        if (parent.getKind() == Tree.Kind.METHOD_INVOCATION) {
          // Allow new MyInternType().intern(), where "intern" is any method marked @InternMethod.
          ExecutableElement elt = TreeUtils.elementFromUse((MethodInvocationTree) parent);
          if (atypeFactory.getDeclAnnotation(elt, InternMethod.class) != null) {
            return true;
          }
        }
      }
    }

    checker.reportError(newInternedObject, "interned.object.creation");
    return false;
  }

  // **********************************************************************
  // Helper methods
  // **********************************************************************

  /**
   * Returns the method that overrides Object.equals, or null.
   *
   * @param node a class
   * @return the class's implementation of equals, or null
   */
  private MethodTree equalsImplementation(ClassTree node) {
    List<? extends Tree> members = node.getMembers();
    for (Tree member : members) {
      if (member instanceof MethodTree) {
        MethodTree mTree = (MethodTree) member;
        ExecutableElement enclosing = TreeUtils.elementFromDeclaration(mTree);
        if (overrides(enclosing, Object.class, "equals")) {
          return mTree;
        }
      }
    }
    return null;
  }

  /**
   * Tests whether a method invocation is an invocation of {@link #equals} with one argument.
   *
   * <p>Returns true even if a method overloads {@link Object#equals(Object)}, because of the common
   * idiom of writing an equals method with a non-Object parameter, in addition to the equals method
   * that overrides {@link Object#equals(Object)}.
   *
   * @param node a method invocation node
   * @return true iff {@code node} is a invocation of {@code equals()}
   */
  private boolean isInvocationOfEquals(MethodInvocationTree node) {
    ExecutableElement method = TreeUtils.elementFromUse(node);
    return (method.getParameters().size() == 1
        && method.getReturnType().getKind() == TypeKind.BOOLEAN
        // method symbols only have simple names
        && method.getSimpleName().contentEquals("equals"));
  }

  /**
   * Pattern matches particular comparisons to avoid common false positives in the {@link
   * Comparable#compareTo(Object)} and {@link Object#equals(Object)}.
   *
   * <p>Specifically, this method tests if: the comparison is a == comparison, it is the test of an
   * if statement that's the first statement in the method, and one of the following is true:
   *
   * <ol>
   *   <li>the method overrides {@link Comparator#compare}, the "then" branch of the if statement
   *       returns zero, and the comparison tests equality of the method's two parameters
   *   <li>the method overrides {@link Object#equals(Object)} and the comparison tests "this"
   *       against the method's parameter
   *   <li>the method overrides {@link Comparable#compareTo(Object)}, the "then" branch of the if
   *       statement returns zero, and the comparison tests "this" against the method's parameter
   * </ol>
   *
   * @param node the comparison to check
   * @return true if one of the supported heuristics is matched, false otherwise
   */
  // TODO: handle != comparisons too!
  // TODO: handle more methods, such as early return from addAll when this == arg
  private boolean suppressInsideComparison(final BinaryTree node) {
    // Only handle == binary trees
    if (node.getKind() != Tree.Kind.EQUAL_TO) {
      return false;
    }

    Tree left = node.getLeftOperand();
    Tree right = node.getRightOperand();

    // Only valid if we're comparing identifiers.
    if (!(left.getKind() == Tree.Kind.IDENTIFIER && right.getKind() == Tree.Kind.IDENTIFIER)) {
      return false;
    }

    TreePath path = getCurrentPath();
    TreePath parentPath = path.getParentPath();
    Tree parent = parentPath.getLeaf();

    // Ensure the == is in a return or in an if, and that enclosing statement is the first
    // statement in the method.
    if (parent.getKind() == Tree.Kind.RETURN) {
      // ensure the return statement is the first statement in the method
      if (parentPath.getParentPath().getParentPath().getLeaf().getKind() != Tree.Kind.METHOD) {
        return false;
      }

      // maybe set some variables??
    } else if (Heuristics.matchParents(getCurrentPath(), Tree.Kind.IF, Tree.Kind.METHOD)) {
      // Ensure the if statement is the first statement in the method

      // Retrieve the enclosing if statement tree and method tree
      Tree ifStatementTree = null;
      MethodTree methodTree = null;
      // Set ifStatementTree and methodTree
      {
        TreePath ppath = parentPath;
        Tree tree;
        while ((tree = ppath.getLeaf()) != null) {
          if (tree.getKind() == Tree.Kind.IF) {
            ifStatementTree = tree;
          } else if (tree.getKind() == Tree.Kind.METHOD) {
            methodTree = (MethodTree) tree;
            break;
          }
          ppath = ppath.getParentPath();
        }
      }
      assert ifStatementTree != null;
      assert methodTree != null;
      StatementTree firstStmnt = methodTree.getBody().getStatements().get(0);
      assert firstStmnt != null;
      @SuppressWarnings("interning:not.interned") // comparing AST nodes
      boolean notSameNode = firstStmnt != ifStatementTree;
      if (notSameNode) {
        return false; // The if statement is not the first statement in the method.
      }
    } else {
      return false;
    }

    ExecutableElement enclosingMethod =
        TreeUtils.elementFromDeclaration(visitorState.getMethodTree());
    assert enclosingMethod != null;

    final Element lhs = TreeUtils.elementFromUse((IdentifierTree) left);
    final Element rhs = TreeUtils.elementFromUse((IdentifierTree) right);

    // Matcher to check for if statement that returns zero
    Heuristics.Matcher matcherIfReturnsZero =
        new Heuristics.Matcher() {

          @Override
          public Boolean visitIf(IfTree tree, Void p) {
            return visit(tree.getThenStatement(), p);
          }

          @Override
          public Boolean visitBlock(BlockTree tree, Void p) {
            if (tree.getStatements().isEmpty()) {
              return false;
            }
            return visit(tree.getStatements().get(0), p);
          }

          @Override
          public Boolean visitReturn(ReturnTree tree, Void p) {
            ExpressionTree expr = tree.getExpression();
            return (expr != null
                && expr.getKind() == Tree.Kind.INT_LITERAL
                && ((LiteralTree) expr).getValue().equals(0));
          }
        };

    boolean hasCompareToMethodAnno =
        atypeFactory.getDeclAnnotation(enclosingMethod, CompareToMethod.class) != null;
    boolean hasEqualsMethodAnno =
        atypeFactory.getDeclAnnotation(enclosingMethod, EqualsMethod.class) != null;
    int params = enclosingMethod.getParameters().size();

    // Determine whether or not the "then" statement of the if has a single
    // "return 0" statement (for the Comparator.compare heuristic).
    if (overrides(enclosingMethod, Comparator.class, "compare")
        || (hasCompareToMethodAnno && params == 2)) {
      final boolean returnsZero =
          new Heuristics.Within(new Heuristics.OfKind(Tree.Kind.IF, matcherIfReturnsZero))
              .match(getCurrentPath());

      if (!returnsZero) {
        return false;
      }

      assert params == 2;
      Element p1 = enclosingMethod.getParameters().get(0);
      Element p2 = enclosingMethod.getParameters().get(1);
      return (p1.equals(lhs) && p2.equals(rhs)) || (p1.equals(rhs) && p2.equals(lhs));

    } else if (overrides(enclosingMethod, Object.class, "equals")
        || (hasEqualsMethodAnno && params == 1)) {
      assert params == 1;
      Element param = enclosingMethod.getParameters().get(0);
      Element thisElt = getThis(trees.getScope(getCurrentPath()));
      assert thisElt != null;
      return (thisElt.equals(lhs) && param.equals(rhs))
          || (thisElt.equals(rhs) && param.equals(lhs));

    } else if (hasEqualsMethodAnno && params == 2) {
      Element p1 = enclosingMethod.getParameters().get(0);
      Element p2 = enclosingMethod.getParameters().get(1);
      return (p1.equals(lhs) && p2.equals(rhs)) || (p1.equals(rhs) && p2.equals(lhs));

    } else if (overrides(enclosingMethod, Comparable.class, "compareTo")
        || (hasCompareToMethodAnno && params == 1)) {

      final boolean returnsZero =
          new Heuristics.Within(new Heuristics.OfKind(Tree.Kind.IF, matcherIfReturnsZero))
              .match(getCurrentPath());

      if (!returnsZero) {
        return false;
      }

      assert params == 1;
      Element param = enclosingMethod.getParameters().get(0);
      Element thisElt = getThis(trees.getScope(getCurrentPath()));
      assert thisElt != null;
      return (thisElt.equals(lhs) && param.equals(rhs))
          || (thisElt.equals(rhs) && param.equals(lhs));
    }

    return false;
  }

  /**
   * Pattern matches to prevent false positives of the forms:
   *
   * <pre>{@code
   * (a == b) || a.equals(b)
   * (a == b) || (a != null ? a.equals(b) : false)
   * (a == b) || (a != null && a.equals(b))
   * }</pre>
   *
   * Returns true iff the given node fits this pattern.
   *
   * @return true iff the node fits a pattern such as (a == b || a.equals(b))
   */
  private boolean suppressEarlyEquals(final BinaryTree node) {
    // Only handle == binary trees
    if (node.getKind() != Tree.Kind.EQUAL_TO) {
      return false;
    }

    // should strip parens
    final ExpressionTree left = TreeUtils.withoutParens(node.getLeftOperand());
    final ExpressionTree right = TreeUtils.withoutParens(node.getRightOperand());

    // looking for ((a == b || a.equals(b))
    Heuristics.Matcher matcherEqOrEquals =
        new Heuristics.Matcher() {

          /** Returns true if e is either "e1 != null" or "e2 != null". */
          private boolean isNeqNull(ExpressionTree e, ExpressionTree e1, ExpressionTree e2) {
            e = TreeUtils.withoutParens(e);
            if (e.getKind() != Tree.Kind.NOT_EQUAL_TO) {
              return false;
            }
            ExpressionTree neqLeft = ((BinaryTree) e).getLeftOperand();
            ExpressionTree neqRight = ((BinaryTree) e).getRightOperand();
            return (((TreeUtils.sameTree(neqLeft, e1) || TreeUtils.sameTree(neqLeft, e2))
                    && neqRight.getKind() == Tree.Kind.NULL_LITERAL)
                // also check for "null != e1" and "null != e2"
                || ((TreeUtils.sameTree(neqRight, e1) || TreeUtils.sameTree(neqRight, e2))
                    && neqLeft.getKind() == Tree.Kind.NULL_LITERAL));
          }

          @Override
          public Boolean visitBinary(BinaryTree tree, Void p) {
            ExpressionTree leftTree = tree.getLeftOperand();
            ExpressionTree rightTree = tree.getRightOperand();

            if (tree.getKind() == Tree.Kind.CONDITIONAL_OR) {
              if (TreeUtils.sameTree(leftTree, node)) {
                // left is "a==b"
                // check right, which should be a.equals(b) or b.equals(a) or similar
                return visit(rightTree, p);
              } else {
                return false;
              }
            }

            if (tree.getKind() == Tree.Kind.CONDITIONAL_AND) {
              // looking for: (a != null && a.equals(b)))
              if (isNeqNull(leftTree, left, right)) {
                return visit(rightTree, p);
              }
              return false;
            }

            return false;
          }

          @Override
          public Boolean visitConditionalExpression(ConditionalExpressionTree tree, Void p) {
            // looking for: (a != null ? a.equals(b) : false)
            ExpressionTree cond = tree.getCondition();
            ExpressionTree trueExp = tree.getTrueExpression();
            ExpressionTree falseExp = tree.getFalseExpression();
            if (isNeqNull(cond, left, right)
                && (falseExp.getKind() == Tree.Kind.BOOLEAN_LITERAL)
                && ((LiteralTree) falseExp).getValue().equals(false)) {
              return visit(trueExp, p);
            }
            return false;
          }

          @Override
          public Boolean visitMethodInvocation(MethodInvocationTree tree, Void p) {
            if (!isInvocationOfEquals(tree)) {
              return false;
            }

            List<? extends ExpressionTree> args = tree.getArguments();
            if (args.size() != 1) {
              return false;
            }
            ExpressionTree arg = args.get(0);
            // if (arg.getKind() != Tree.Kind.IDENTIFIER) {
            //     return false;
            // }
            // Element argElt = TreeUtils.elementFromUse((IdentifierTree) arg);

            ExpressionTree exp = tree.getMethodSelect();
            if (exp.getKind() != Tree.Kind.MEMBER_SELECT) {
              return false;
            }
            MemberSelectTree member = (MemberSelectTree) exp;
            ExpressionTree receiver = member.getExpression();
            // Element refElt = TreeUtils.elementFromUse(receiver);

            // if (!((refElt.equals(lhs) && argElt.equals(rhs)) ||
            //       ((refElt.equals(rhs) && argElt.equals(lhs))))) {
            //     return false;
            // }

            if (TreeUtils.sameTree(receiver, left) && TreeUtils.sameTree(arg, right)) {
              return true;
            }
            if (TreeUtils.sameTree(receiver, right) && TreeUtils.sameTree(arg, left)) {
              return true;
            }

            return false;
          }
        };

    boolean okay =
        new Heuristics.Within(new Heuristics.OfKind(Tree.Kind.CONDITIONAL_OR, matcherEqOrEquals))
            .match(getCurrentPath());
    return okay;
  }

  /**
   * Pattern matches to prevent false positives of the form {@code (a == b || a.compareTo(b) == 0)}.
   * Returns true iff the given node fits this pattern.
   *
   * @return true iff the node fits the pattern (a == b || a.compareTo(b) == 0)
   */
  private boolean suppressEarlyCompareTo(final BinaryTree node) {
    // Only handle == binary trees
    if (node.getKind() != Tree.Kind.EQUAL_TO) {
      return false;
    }

    Tree left = TreeUtils.withoutParens(node.getLeftOperand());
    Tree right = TreeUtils.withoutParens(node.getRightOperand());

    // Only valid if we're comparing identifiers.
    if (!(left.getKind() == Tree.Kind.IDENTIFIER && right.getKind() == Tree.Kind.IDENTIFIER)) {
      return false;
    }

    final Element lhs = TreeUtils.elementFromUse((IdentifierTree) left);
    final Element rhs = TreeUtils.elementFromUse((IdentifierTree) right);

    // looking for ((a == b || a.compareTo(b) == 0)
    Heuristics.Matcher matcherEqOrCompareTo =
        new Heuristics.Matcher() {

          @Override
          public Boolean visitBinary(BinaryTree tree, Void p) {
            if (tree.getKind() == Tree.Kind.EQUAL_TO) { // a.compareTo(b) == 0
              ExpressionTree leftTree = tree.getLeftOperand(); // looking for a.compareTo(b) or
              // b.compareTo(a)
              ExpressionTree rightTree = tree.getRightOperand(); // looking for 0

              if (rightTree.getKind() != Tree.Kind.INT_LITERAL) {
                return false;
              }
              LiteralTree rightLiteral = (LiteralTree) rightTree;
              if (!rightLiteral.getValue().equals(0)) {
                return false;
              }

              return visit(leftTree, p);
            } else {
              // a == b || a.compareTo(b) == 0
              @SuppressWarnings("interning:assignment" // AST node comparisons
              )
              @InternedDistinct ExpressionTree leftTree = tree.getLeftOperand(); // looking for a==b
              ExpressionTree rightTree = tree.getRightOperand(); // looking for a.compareTo(b) == 0
              // or b.compareTo(a) == 0
              if (leftTree != node) {
                return false;
              }
              if (rightTree.getKind() != Tree.Kind.EQUAL_TO) {
                return false;
              }
              return visit(rightTree, p);
            }
          }

          @Override
          public Boolean visitMethodInvocation(MethodInvocationTree tree, Void p) {
            if (!TreeUtils.isMethodInvocation(
                tree, comparableCompareTo, checker.getProcessingEnvironment())) {
              return false;
            }

            List<? extends ExpressionTree> args = tree.getArguments();
            if (args.size() != 1) {
              return false;
            }
            ExpressionTree arg = args.get(0);
            if (arg.getKind() != Tree.Kind.IDENTIFIER) {
              return false;
            }
            Element argElt = TreeUtils.elementFromUse(arg);

            ExpressionTree exp = tree.getMethodSelect();
            if (exp.getKind() != Tree.Kind.MEMBER_SELECT) {
              return false;
            }
            MemberSelectTree member = (MemberSelectTree) exp;
            if (member.getExpression().getKind() != Tree.Kind.IDENTIFIER) {
              return false;
            }

            Element refElt = TreeUtils.elementFromUse(member.getExpression());

            if (!((refElt.equals(lhs) && argElt.equals(rhs))
                || (refElt.equals(rhs) && argElt.equals(lhs)))) {
              return false;
            }
            return true;
          }
        };

    boolean okay =
        new Heuristics.Within(new Heuristics.OfKind(Tree.Kind.CONDITIONAL_OR, matcherEqOrCompareTo))
            .match(getCurrentPath());
    return okay;
  }

  /**
   * Given {@code a == b}, where a has type A and b has type B, don't issue a warning when either
   * the declaration of A or that of B is annotated with @Interned because {@code a == b} will be
   * true only if a's run-time type is B (or lower), in which case a is actually interned.
   */
  private boolean suppressEqualsIfClassIsAnnotated(
      AnnotatedTypeMirror left, AnnotatedTypeMirror right) {
    // It would be better to just test their greatest lower bound.
    // That could permit some comparisons that this forbids.
    return classIsAnnotated(left) || classIsAnnotated(right);
  }

  /** Returns true if the type's declaration has an @Interned annotation. */
  private boolean classIsAnnotated(AnnotatedTypeMirror type) {

    TypeMirror tm = type.getUnderlyingType();
    if (tm == null) {
      // Maybe a type variable or wildcard had no upper bound
      return false;
    }

    tm = TypesUtils.findConcreteUpperBound(tm);
    if (tm == null || tm.getKind() == TypeKind.ARRAY) {
      // Bound of a wildcard might be null
      return false;
    }

    if (tm.getKind() != TypeKind.DECLARED) {
      checker.message(
          Kind.WARNING, "InterningVisitor.classIsAnnotated: tm = %s (%s)", tm, tm.getClass());
    }
    Element classElt = ((DeclaredType) tm).asElement();
    if (classElt == null) {
      checker.message(
          Kind.WARNING,
          "InterningVisitor.classIsAnnotated: classElt = null for tm = %s (%s)",
          tm,
          tm.getClass());
    }
    if (classElt != null) {
      Set<AnnotationMirror> bound = atypeFactory.getTypeDeclarationBounds(tm);
      return atypeFactory.containsSameByClass(bound, Interned.class);
    }
    return false;
  }

  /**
   * Determines the element corresponding to "this" inside a scope. Returns null within static
   * methods.
   *
   * @param scope the scope to search for the element corresponding to "this" in
   * @return the element corresponding to "this" in the given scope, or null if not found
   */
  private Element getThis(Scope scope) {
    for (Element e : scope.getLocalElements()) {
      if (e.getSimpleName().contentEquals("this")) {
        return e;
      }
    }
    return null;
  }

  /**
   * Determines whether or not the given element overrides the named method in the named class.
   *
   * @param e an element for a method
   * @param clazz the class
   * @param method the name of a method
   * @return true if the method given by {@code e} overrides the named method in the named class;
   *     false otherwise
   */
  private boolean overrides(ExecutableElement e, Class<?> clazz, String method) {

    // Get the element named by "clazz".
    TypeElement clazzElt = elements.getTypeElement(clazz.getCanonicalName());
    assert clazzElt != null;

    // Check all of the methods in the class for name matches and overriding.
    for (ExecutableElement elt : ElementFilter.methodsIn(clazzElt.getEnclosedElements())) {
      if (elt.getSimpleName().contentEquals(method) && elements.overrides(e, elt, clazzElt)) {
        return true;
      }
    }

    return false;
  }

  /**
   * Returns the type to check.
   *
   * @return the type to check
   */
  DeclaredType typeToCheck() {
    @SuppressWarnings("signature:assignment") // user input
    @CanonicalName String className = checker.getOption("checkclass");
    if (className == null) {
      return null;
    }

    TypeElement classElt = elements.getTypeElement(className);
    if (classElt == null) {
      return null;
    }

    return types.getDeclaredType(classElt);
  }

  @Override
  protected boolean isTypeCastSafe(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) {
    if (castType.getKind().isPrimitive()) {
      return true;
    }
    return super.isTypeCastSafe(castType, exprType);
  }
}
