package org.checkerframework.dataflow.expression;

import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
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.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.interning.qual.EqualsMethod;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.ArrayAccessNode;
import org.checkerframework.dataflow.cfg.node.ArrayCreationNode;
import org.checkerframework.dataflow.cfg.node.BinaryOperationNode;
import org.checkerframework.dataflow.cfg.node.ClassNameNode;
import org.checkerframework.dataflow.cfg.node.ExplicitThisNode;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.NarrowingConversionNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.StringConversionNode;
import org.checkerframework.dataflow.cfg.node.SuperNode;
import org.checkerframework.dataflow.cfg.node.ThisNode;
import org.checkerframework.dataflow.cfg.node.UnaryOperationNode;
import org.checkerframework.dataflow.cfg.node.ValueLiteralNode;
import org.checkerframework.dataflow.cfg.node.WideningConversionNode;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;

// The Lock Checker also supports "<self>" as a JavaExpression, but that is implemented in the Lock
// Checker.
// There are no special subclasses (AST nodes) for "<self>".
/**
 * This class represents a Java expression and its type. It does not represent all possible Java
 * expressions (for example, it does not represent a ternary conditional expression {@code ?:}; use
 * {@link org.checkerframework.dataflow.expression.Unknown} for unrepresentable expressions).
 *
 * <p>This class's representation is like an AST: subparts are also expressions. For declared names
 * (fields, local variables, and methods), it also contains an Element.
 *
 * <p>Each subclass represents a different type of expression, such as {@link
 * org.checkerframework.dataflow.expression.MethodCall}, {@link
 * org.checkerframework.dataflow.expression.ArrayAccess}, {@link
 * org.checkerframework.dataflow.expression.LocalVariable}, etc.
 *
 * @see <a href="https://checkerframework.org/manual/#java-expressions-as-arguments">the syntax of
 *     Java expressions supported by the Checker Framework</a>
 */
public abstract class JavaExpression {
  /** The type of this expression. */
  protected final TypeMirror type;

  /**
   * Create a JavaExpression.
   *
   * @param type the type of the expression
   */
  protected JavaExpression(TypeMirror type) {
    assert type != null;
    this.type = type;
  }

  public TypeMirror getType() {
    return type;
  }

  public abstract boolean containsOfClass(Class<? extends JavaExpression> clazz);

  public boolean containsUnknown() {
    return containsOfClass(Unknown.class);
  }

  /**
   * Returns true if the expression is deterministic.
   *
   * @param provider an annotation provider (a type factory)
   * @return true if this expression is deterministic
   */
  public abstract boolean isDeterministic(AnnotationProvider provider);

  /**
   * Returns true if all the expressions in the list are deterministic.
   *
   * @param list the list whose elements to test
   * @param provider an annotation provider (a type factory)
   * @return true if all the expressions in the list are deterministic
   */
  @SuppressWarnings("nullness:dereference.of.nullable") // flow within a lambda
  public static boolean listIsDeterministic(
      List<? extends @Nullable JavaExpression> list, AnnotationProvider provider) {
    return list.stream().allMatch(je -> je == null || je.isDeterministic(provider));
  }

  /**
   * Returns true if and only if the value this expression stands for cannot be changed (with
   * respect to ==) by a method call. This is the case for local variables, the self reference,
   * final field accesses whose receiver is {@link #isUnassignableByOtherCode}, and operations whose
   * operands are all {@link #isUnmodifiableByOtherCode}.
   *
   * @see #isUnmodifiableByOtherCode
   */
  public abstract boolean isUnassignableByOtherCode();

  /**
   * Returns true if and only if the value this expression stands for cannot be changed by a method
   * call, including changes to any of its fields.
   *
   * <p>Approximately, this returns true if the expression is {@link #isUnassignableByOtherCode} and
   * its type is immutable.
   *
   * @see #isUnassignableByOtherCode
   */
  public abstract boolean isUnmodifiableByOtherCode();

  /**
   * Returns true if and only if the two Java expressions are syntactically identical.
   *
   * <p>This exists for use by {@link #containsSyntacticEqualJavaExpression}.
   *
   * @param je the other Java expression to compare to this one
   * @return true if and only if the two Java expressions are syntactically identical
   */
  @EqualsMethod
  public abstract boolean syntacticEquals(JavaExpression je);

  /**
   * Returns true if the corresponding list elements satisfy {@link #syntacticEquals}.
   *
   * @param lst1 the first list to compare
   * @param lst2 the second list to compare
   * @return true if the corresponding list elements satisfy {@link #syntacticEquals}
   */
  static boolean syntacticEqualsList(
      List<? extends @Nullable JavaExpression> lst1,
      List<? extends @Nullable JavaExpression> lst2) {
    if (lst1.size() != lst2.size()) {
      return false;
    }
    for (int i = 0; i < lst1.size(); i++) {
      JavaExpression dim1 = lst1.get(i);
      JavaExpression dim2 = lst2.get(i);
      if (dim1 == null && dim2 == null) {
        continue;
      } else if (dim1 == null || dim2 == null) {
        return false;
      } else {
        if (!dim1.syntacticEquals(dim2)) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Returns true if and only if this contains a JavaExpression that is syntactically equal to
   * {@code other}.
   *
   * @param other the JavaExpression to search for
   * @return true if and only if this contains a JavaExpression that is syntactically equal to
   *     {@code other}
   */
  public abstract boolean containsSyntacticEqualJavaExpression(JavaExpression other);

  /**
   * Returns true if the given list contains a JavaExpression that is syntactically equal to {@code
   * other}.
   *
   * @param list the list in which to search for a match
   * @param other the JavaExpression to search for
   * @return true if and only if the list contains a JavaExpression that is syntactically equal to
   *     {@code other}
   */
  @SuppressWarnings("nullness:dereference.of.nullable") // flow within a lambda
  public static boolean listContainsSyntacticEqualJavaExpression(
      List<? extends @Nullable JavaExpression> list, JavaExpression other) {
    return list.stream()
        .anyMatch(je -> je != null && je.containsSyntacticEqualJavaExpression(other));
  }

  /**
   * Returns true if and only if {@code other} appears anywhere in this or an expression appears in
   * this such that {@code other} might alias this expression, and that expression is modifiable.
   *
   * <p>This is always true, except for cases where the Java type information prevents aliasing and
   * none of the subexpressions can alias 'other'.
   */
  public boolean containsModifiableAliasOf(Store<?> store, JavaExpression other) {
    return this.equals(other) || store.canAlias(this, other);
  }

  /**
   * Format this verbosely, for debugging.
   *
   * @return a verbose string representation of this
   */
  public String toStringDebug() {
    return String.format("%s(%s): %s", getClass().getSimpleName(), type, toString());
  }

  ///
  /// Static methods
  ///

  /**
   * Returns the Java expression for a {@link FieldAccessNode}. The result may contain {@link
   * Unknown} as receiver.
   *
   * @param node the FieldAccessNode to convert to a JavaExpression
   * @return the {@link FieldAccess} or {@link ClassName} that corresponds to {@code node}
   */
  public static JavaExpression fromNodeFieldAccess(FieldAccessNode node) {
    Node receiverNode = node.getReceiver();
    String fieldName = node.getFieldName();
    if (fieldName.equals("this")) {
      // The CFG represents "className.this" as a FieldAccessNode, but it isn't a field access.
      return new ThisReference(receiverNode.getType());
    } else if (fieldName.equals("class")) {
      // The CFG represents "className.class" as a FieldAccessNode; bit it is a class literal.
      return new ClassName(receiverNode.getType());
    }
    JavaExpression receiver;
    if (node.isStatic()) {
      receiver = new ClassName(receiverNode.getType());
    } else {
      receiver = fromNode(receiverNode);
    }
    return new FieldAccess(receiver, node);
  }

  /**
   * Returns the internal representation (as {@link FieldAccess}) of a {@link FieldAccessNode}. The
   * result may contain {@link Unknown} as receiver.
   *
   * @param node the ArrayAccessNode to convert to a JavaExpression
   * @return the internal representation (as {@link FieldAccess}) of a {@link FieldAccessNode}. Can
   *     contain {@link Unknown} as receiver.
   */
  public static ArrayAccess fromArrayAccess(ArrayAccessNode node) {
    JavaExpression array = fromNode(node.getArray());
    JavaExpression index = fromNode(node.getIndex());
    return new ArrayAccess(node.getType(), array, index);
  }

  /**
   * We ignore operations such as widening and narrowing when computing the internal representation.
   *
   * @param receiverNode a node to convert to a JavaExpression
   * @return the internal representation of the given node. Might contain {@link Unknown}.
   */
  public static JavaExpression fromNode(Node receiverNode) {
    JavaExpression result = null;
    if (receiverNode instanceof FieldAccessNode) {
      result = fromNodeFieldAccess((FieldAccessNode) receiverNode);
    } else if (receiverNode instanceof ExplicitThisNode) {
      result = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof ThisNode) {
      result = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof SuperNode) {
      result = new ThisReference(receiverNode.getType());
    } else if (receiverNode instanceof LocalVariableNode) {
      LocalVariableNode lv = (LocalVariableNode) receiverNode;
      result = new LocalVariable(lv);
    } else if (receiverNode instanceof ArrayAccessNode) {
      ArrayAccessNode a = (ArrayAccessNode) receiverNode;
      result = fromArrayAccess(a);
    } else if (receiverNode instanceof StringConversionNode) {
      // ignore string conversion
      return fromNode(((StringConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof WideningConversionNode) {
      // ignore widening
      return fromNode(((WideningConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof NarrowingConversionNode) {
      // ignore narrowing
      return fromNode(((NarrowingConversionNode) receiverNode).getOperand());
    } else if (receiverNode instanceof UnaryOperationNode) {
      UnaryOperationNode uopn = (UnaryOperationNode) receiverNode;
      return new UnaryOperation(uopn, fromNode(uopn.getOperand()));
    } else if (receiverNode instanceof BinaryOperationNode) {
      BinaryOperationNode bopn = (BinaryOperationNode) receiverNode;
      return new BinaryOperation(
          bopn, fromNode(bopn.getLeftOperand()), fromNode(bopn.getRightOperand()));
    } else if (receiverNode instanceof ClassNameNode) {
      ClassNameNode cn = (ClassNameNode) receiverNode;
      result = new ClassName(cn.getType());
    } else if (receiverNode instanceof ValueLiteralNode) {
      ValueLiteralNode vn = (ValueLiteralNode) receiverNode;
      result = new ValueLiteral(vn.getType(), vn);
    } else if (receiverNode instanceof ArrayCreationNode) {
      ArrayCreationNode an = (ArrayCreationNode) receiverNode;
      List<@Nullable JavaExpression> dimensions =
          CollectionsPlume.mapList(JavaExpression::fromNode, an.getDimensions());
      List<JavaExpression> initializers =
          CollectionsPlume.mapList(JavaExpression::fromNode, an.getInitializers());
      result = new ArrayCreation(an.getType(), dimensions, initializers);
    } else if (receiverNode instanceof MethodInvocationNode) {
      MethodInvocationNode mn = (MethodInvocationNode) receiverNode;
      MethodInvocationTree t = mn.getTree();
      if (t == null) {
        throw new BugInCF("Unexpected null tree for node: " + mn);
      }
      assert TreeUtils.isUseOfElement(t) : "@AssumeAssertion(nullness): tree kind";
      ExecutableElement invokedMethod = TreeUtils.elementFromUse(t);

      // Note that the method might be nondeterministic.
      List<JavaExpression> parameters =
          CollectionsPlume.mapList(JavaExpression::fromNode, mn.getArguments());
      JavaExpression methodReceiver;
      if (ElementUtils.isStatic(invokedMethod)) {
        methodReceiver = new ClassName(mn.getTarget().getReceiver().getType());
      } else {
        methodReceiver = fromNode(mn.getTarget().getReceiver());
      }
      result = new MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters);
    }

    if (result == null) {
      result = new Unknown(receiverNode);
    }
    return result;
  }

  /**
   * Converts a javac {@link ExpressionTree} to a CF JavaExpression. The result might contain {@link
   * Unknown}.
   *
   * <p>We ignore operations such as widening and narrowing when computing the JavaExpression.
   *
   * @param tree a javac tree
   * @return a JavaExpression for the given javac tree
   */
  public static JavaExpression fromTree(ExpressionTree tree) {
    JavaExpression result;
    switch (tree.getKind()) {
      case ARRAY_ACCESS:
        ArrayAccessTree a = (ArrayAccessTree) tree;
        JavaExpression arrayAccessExpression = fromTree(a.getExpression());
        JavaExpression index = fromTree(a.getIndex());
        result = new ArrayAccess(TreeUtils.typeOf(a), arrayAccessExpression, index);
        break;

      case BOOLEAN_LITERAL:
      case CHAR_LITERAL:
      case DOUBLE_LITERAL:
      case FLOAT_LITERAL:
      case INT_LITERAL:
      case LONG_LITERAL:
      case NULL_LITERAL:
      case STRING_LITERAL:
        LiteralTree vn = (LiteralTree) tree;
        result = new ValueLiteral(TreeUtils.typeOf(tree), vn.getValue());
        break;

      case NEW_ARRAY:
        NewArrayTree newArrayTree = (NewArrayTree) tree;
        List<@Nullable JavaExpression> dimensions;
        if (newArrayTree.getDimensions() == null) {
          dimensions = Collections.emptyList();
        } else {
          dimensions = new ArrayList<>(newArrayTree.getDimensions().size());
          for (ExpressionTree dimension : newArrayTree.getDimensions()) {
            dimensions.add(fromTree(dimension));
          }
        }
        List<JavaExpression> initializers;
        if (newArrayTree.getInitializers() == null) {
          initializers = Collections.emptyList();
        } else {
          initializers = new ArrayList<>(newArrayTree.getInitializers().size());
          for (ExpressionTree initializer : newArrayTree.getInitializers()) {
            initializers.add(fromTree(initializer));
          }
        }

        result = new ArrayCreation(TreeUtils.typeOf(tree), dimensions, initializers);
        break;

      case METHOD_INVOCATION:
        MethodInvocationTree mn = (MethodInvocationTree) tree;
        assert TreeUtils.isUseOfElement(mn) : "@AssumeAssertion(nullness): tree kind";
        ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn);

        // Note that the method might be nondeterministic.
        List<JavaExpression> parameters =
            CollectionsPlume.mapList(JavaExpression::fromTree, mn.getArguments());
        JavaExpression methodReceiver;
        if (ElementUtils.isStatic(invokedMethod)) {
          @SuppressWarnings(
              "nullness:assignment" // enclosingTypeElement(ExecutableElement): @NonNull
          )
          @NonNull TypeElement methodType = ElementUtils.enclosingTypeElement(invokedMethod);
          methodReceiver = new ClassName(methodType.asType());
        } else {
          methodReceiver = getReceiver(mn);
        }
        TypeMirror resultType = TreeUtils.typeOf(mn);
        result = new MethodCall(resultType, invokedMethod, methodReceiver, parameters);
        break;

      case MEMBER_SELECT:
        result = fromMemberSelect((MemberSelectTree) tree);
        break;

      case IDENTIFIER:
        IdentifierTree identifierTree = (IdentifierTree) tree;
        TypeMirror typeOfId = TreeUtils.typeOf(identifierTree);
        Name identifierName = identifierTree.getName();
        if (identifierName.contentEquals("this") || identifierName.contentEquals("super")) {
          result = new ThisReference(typeOfId);
          break;
        }
        assert TreeUtils.isUseOfElement(identifierTree) : "@AssumeAssertion(nullness): tree kind";
        Element ele = TreeUtils.elementFromUse(identifierTree);
        if (ElementUtils.isTypeElement(ele)) {
          result = new ClassName(ele.asType());
          break;
        }
        result = fromVariableElement(typeOfId, ele);
        break;

      case UNARY_PLUS:
        return fromTree(((UnaryTree) tree).getExpression());
      case BITWISE_COMPLEMENT:
      case LOGICAL_COMPLEMENT:
      case POSTFIX_DECREMENT:
      case POSTFIX_INCREMENT:
      case PREFIX_DECREMENT:
      case PREFIX_INCREMENT:
      case UNARY_MINUS:
        JavaExpression operand = fromTree(((UnaryTree) tree).getExpression());
        return new UnaryOperation(TreeUtils.typeOf(tree), tree.getKind(), operand);

      case CONDITIONAL_AND:
      case CONDITIONAL_OR:
      case DIVIDE:
      case EQUAL_TO:
      case GREATER_THAN:
      case GREATER_THAN_EQUAL:
      case LEFT_SHIFT:
      case LESS_THAN:
      case LESS_THAN_EQUAL:
      case MINUS:
      case MULTIPLY:
      case NOT_EQUAL_TO:
      case OR:
      case PLUS:
      case REMAINDER:
      case RIGHT_SHIFT:
      case UNSIGNED_RIGHT_SHIFT:
      case XOR:
        BinaryTree binaryTree = (BinaryTree) tree;
        JavaExpression left = fromTree(binaryTree.getLeftOperand());
        JavaExpression right = fromTree(binaryTree.getRightOperand());
        return new BinaryOperation(TreeUtils.typeOf(tree), tree.getKind(), left, right);

      default:
        result = null;
    }

    if (result == null) {
      result = new Unknown(tree);
    }
    return result;
  }

  /**
   * Returns the Java expression corresponding to the given variable tree {@code tree}.
   *
   * @param tree a variable tree
   * @return a JavaExpression for {@code tree}
   */
  public static JavaExpression fromVariableTree(VariableTree tree) {
    return fromVariableElement(TreeUtils.typeOf(tree), TreeUtils.elementFromDeclaration(tree));
  }

  /**
   * Returns the Java expression corresponding to the given variable element {@code ele}.
   *
   * @param typeOfEle the type of {@code ele}
   * @param ele element whose JavaExpression is returned
   * @return the Java expression corresponding to the given variable element {@code ele}
   */
  private static JavaExpression fromVariableElement(TypeMirror typeOfEle, Element ele) {
    switch (ele.getKind()) {
      case LOCAL_VARIABLE:
      case RESOURCE_VARIABLE:
      case EXCEPTION_PARAMETER:
      case PARAMETER:
        return new LocalVariable(ele);
      case FIELD:
      case ENUM_CONSTANT:
        // Implicit access expression, such as "this" or a class name
        JavaExpression fieldAccessExpression;
        @SuppressWarnings("nullness:dereference.of.nullable") // a field has enclosing class
        TypeMirror enclosingTypeElement = ElementUtils.enclosingTypeElement(ele).asType();
        if (ElementUtils.isStatic(ele)) {
          fieldAccessExpression = new ClassName(enclosingTypeElement);
        } else {
          fieldAccessExpression = new ThisReference(enclosingTypeElement);
        }
        return new FieldAccess(fieldAccessExpression, typeOfEle, (VariableElement) ele);
      default:
        throw new BugInCF(
            "Unexpected kind of VariableTree: kind: %s element: %s", ele.getKind(), ele);
    }
  }

  /**
   * Creates a JavaExpression from the {@code memberSelectTree}.
   *
   * @param memberSelectTree tree
   * @return a JavaExpression for {@code memberSelectTree}
   */
  private static JavaExpression fromMemberSelect(MemberSelectTree memberSelectTree) {
    TypeMirror expressionType = TreeUtils.typeOf(memberSelectTree.getExpression());
    if (TreeUtils.isClassLiteral(memberSelectTree)) {
      // the identifier is "class"
      return new ClassName(expressionType);
    }
    if (TreeUtils.isExplicitThisDereference(memberSelectTree)) {
      // the identifier is "class"
      return new ThisReference(expressionType);
    }

    assert TreeUtils.isUseOfElement(memberSelectTree) : "@AssumeAssertion(nullness): tree kind";
    Element ele = TreeUtils.elementFromUse(memberSelectTree);
    if (ElementUtils.isTypeElement(ele)) {
      // o instanceof MyClass.InnerClass
      // o instanceof MyClass.InnerInterface
      TypeMirror selectType = TreeUtils.typeOf(memberSelectTree);
      return new ClassName(selectType);
    }
    switch (ele.getKind()) {
      case METHOD:
      case CONSTRUCTOR:
        return fromTree(memberSelectTree.getExpression());
      case ENUM_CONSTANT:
      case FIELD:
        TypeMirror fieldType = TreeUtils.typeOf(memberSelectTree);
        JavaExpression je = fromTree(memberSelectTree.getExpression());
        return new FieldAccess(je, fieldType, (VariableElement) ele);
      default:
        throw new BugInCF("Unexpected element kind: %s element: %s", ele.getKind(), ele);
    }
  }

  /**
   * Returns the parameters of {@code methodEle} as {@link LocalVariable}s.
   *
   * @param methodEle the method element
   * @return list of parameters as {@link LocalVariable}s
   */
  public static List<JavaExpression> getParametersAsLocalVariables(ExecutableElement methodEle) {
    return CollectionsPlume.mapList(LocalVariable::new, methodEle.getParameters());
  }

  /**
   * Returns the parameters of {@code methodEle} as {@link FormalParameter}s.
   *
   * @param methodEle the method element
   * @return list of parameters as {@link FormalParameter}s
   */
  public static List<FormalParameter> getFormalParameters(ExecutableElement methodEle) {
    List<FormalParameter> parameters = new ArrayList<>(methodEle.getParameters().size());
    int oneBasedIndex = 1;
    for (VariableElement variableElement : methodEle.getParameters()) {
      parameters.add(new FormalParameter(oneBasedIndex, variableElement));
      oneBasedIndex++;
    }
    return parameters;
  }

  ///
  /// Obtaining the receiver
  ///

  /**
   * Returns the receiver of the given invocation
   *
   * @param accessTree method or constructor invocation
   * @return the receiver of the given invocation
   */
  public static JavaExpression getReceiver(ExpressionTree accessTree) {
    // TODO: Handle field accesses too?
    assert accessTree instanceof MethodInvocationTree || accessTree instanceof NewClassTree;
    ExpressionTree receiverTree = TreeUtils.getReceiverTree(accessTree);
    if (receiverTree != null) {
      return fromTree(receiverTree);
    } else {
      Element ele = TreeUtils.elementFromUse(accessTree);
      if (ele == null) {
        throw new BugInCF("TreeUtils.elementFromUse(" + accessTree + ") => null");
      }
      return getImplicitReceiver(ele);
    }
  }

  /**
   * Returns the implicit receiver of ele.
   *
   * <p>Returns either a new ClassName or a new ThisReference depending on whether ele is static or
   * not. The passed element must be a field, method, or class.
   *
   * @param ele a field, method, or class
   * @return either a new ClassName or a new ThisReference depending on whether ele is static or not
   */
  public static JavaExpression getImplicitReceiver(Element ele) {
    TypeElement enclosingTypeElement = ElementUtils.enclosingTypeElement(ele);
    if (enclosingTypeElement == null) {
      throw new BugInCF("getImplicitReceiver's arg has no enclosing type: " + ele);
    }
    TypeMirror enclosingType = enclosingTypeElement.asType();
    if (ElementUtils.isStatic(ele)) {
      return new ClassName(enclosingType);
    } else {
      return new ThisReference(enclosingType);
    }
  }

  /**
   * Returns either a new ClassName or ThisReference JavaExpression object for the enclosingType.
   *
   * <p>The Tree should be an expression or a statement that does not have a receiver or an implicit
   * receiver. For example, a local variable declaration.
   *
   * @param path TreePath to tree
   * @param enclosingType type of the enclosing type
   * @return a new ClassName or ThisReference that is a JavaExpression object for the enclosingType
   */
  public static JavaExpression getPseudoReceiver(TreePath path, TypeMirror enclosingType) {
    if (TreePathUtil.isTreeInStaticScope(path)) {
      return new ClassName(enclosingType);
    } else {
      return new ThisReference(enclosingType);
    }
  }

  /**
   * Accept method of the visitor pattern.
   *
   * @param visitor the visitor to be applied to this JavaExpression
   * @param p the parameter for this operation
   * @param <R> result type of the operation
   * @param <P> parameter type
   * @return the result of visiting this
   */
  public abstract <R, P> R accept(JavaExpressionVisitor<R, P> visitor, P p);

  /**
   * Viewpoint-adapts {@code this} to a field access with receiver {@code receiver}.
   *
   * @param receiver receiver of the field access
   * @return viewpoint-adapted version of this
   */
  public JavaExpression atFieldAccess(JavaExpression receiver) {
    return ViewpointAdaptJavaExpression.viewpointAdapt(this, receiver);
  }

  /**
   * Viewpoint-adapts {@code this} to the {@code methodTree} by converting any {@code
   * FormalParameter} into {@code LocalVariable}s.
   *
   * @param methodTree method declaration tree
   * @return viewpoint-adapted version of this
   */
  public final JavaExpression atMethodBody(MethodTree methodTree) {
    List<JavaExpression> parametersJe =
        CollectionsPlume.mapList(
            (VariableTree param) -> new LocalVariable(TreeUtils.elementFromDeclaration(param)),
            methodTree.getParameters());
    return ViewpointAdaptJavaExpression.viewpointAdapt(this, parametersJe);
  }

  /**
   * Viewpoint-adapts {@code this} to the {@code methodInvocationTree}.
   *
   * @param methodInvocationTree method invocation
   * @return viewpoint-adapted version of this
   */
  public final JavaExpression atMethodInvocation(MethodInvocationTree methodInvocationTree) {
    JavaExpression receiverJe = JavaExpression.getReceiver(methodInvocationTree);
    List<JavaExpression> argumentsJe =
        argumentTreesToJavaExpressions(
            TreeUtils.elementFromUse(methodInvocationTree), methodInvocationTree.getArguments());
    return ViewpointAdaptJavaExpression.viewpointAdapt(this, receiverJe, argumentsJe);
  }

  /**
   * Viewpoint-adapts {@code this} to the {@code invocationNode}.
   *
   * @param invocationNode method invocation
   * @return viewpoint-adapted version of this
   */
  public final JavaExpression atMethodInvocation(MethodInvocationNode invocationNode) {
    JavaExpression receiverJe = JavaExpression.fromNode(invocationNode.getTarget().getReceiver());
    List<JavaExpression> argumentsJe =
        CollectionsPlume.mapList(JavaExpression::fromNode, invocationNode.getArguments());
    return ViewpointAdaptJavaExpression.viewpointAdapt(this, receiverJe, argumentsJe);
  }

  /**
   * Viewpoint-adapts {@code this} to the {@code newClassTree}.
   *
   * @param newClassTree constructor invocation
   * @return viewpoint-adapted version of this
   */
  public JavaExpression atConstructorInvocation(NewClassTree newClassTree) {
    JavaExpression receiverJe = JavaExpression.getReceiver(newClassTree);
    List<JavaExpression> argumentsJe =
        argumentTreesToJavaExpressions(
            TreeUtils.elementFromUse(newClassTree), newClassTree.getArguments());
    return ViewpointAdaptJavaExpression.viewpointAdapt(this, receiverJe, argumentsJe);
  }

  /**
   * Converts method or constructor arguments from Trees to JavaExpressions, accounting for varargs.
   *
   * @param method the method or constructor being invoked
   * @param argTrees the arguments to the method or constructor
   * @return the arguments, as JavaExpressions
   */
  private static List<JavaExpression> argumentTreesToJavaExpressions(
      ExecutableElement method, List<? extends ExpressionTree> argTrees) {
    if (isVarArgsInvocation(method, argTrees)) {
      List<JavaExpression> result = new ArrayList<>(method.getParameters().size());
      for (int i = 0; i < method.getParameters().size() - 1; i++) {
        result.add(JavaExpression.fromTree(argTrees.get(i)));
      }

      List<JavaExpression> varargArgs =
          new ArrayList<>(argTrees.size() - method.getParameters().size() + 1);
      for (int i = method.getParameters().size() - 1; i < argTrees.size(); i++) {
        varargArgs.add(JavaExpression.fromTree(argTrees.get(i)));
      }
      Element varargsElement = method.getParameters().get(method.getParameters().size() - 1);
      TypeMirror tm = ElementUtils.getType(varargsElement);
      result.add(new ArrayCreation(tm, Collections.emptyList(), varargArgs));

      return result;
    }

    return CollectionsPlume.mapList(JavaExpression::fromTree, argTrees);
  }

  /**
   * Returns true if method is a varargs method or constructor and its varargs arguments are not
   * passed in an array.
   *
   * @param method the method or constructor
   * @param args the arguments at the call site
   * @return true if method is a varargs method and its varargs arguments are not passed in an array
   */
  private static boolean isVarArgsInvocation(
      ExecutableElement method, List<? extends ExpressionTree> args) {
    if (!method.isVarArgs()) {
      return false;
    }
    if (method.getParameters().size() != args.size()) {
      return true;
    }
    TypeMirror lastArgType = TreeUtils.typeOf(args.get(args.size() - 1));
    if (lastArgType.getKind() != TypeKind.ARRAY) {
      return true;
    }
    List<? extends VariableElement> paramElts = method.getParameters();
    VariableElement lastParamElt = paramElts.get(paramElts.size() - 1);
    return TypesUtils.getArrayDepth(ElementUtils.getType(lastParamElt))
        != TypesUtils.getArrayDepth(lastArgType);
  }
}
