package org.checkerframework.javacutil.trees;

import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.AssignmentTree;
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.NewArrayTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Names;
import java.util.List;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
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.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;

/**
 * The TreeBuilder permits the creation of new AST Trees using the non-public Java compiler API
 * TreeMaker.
 */
public class TreeBuilder {
  protected final Elements elements;
  protected final Types modelTypes;
  protected final com.sun.tools.javac.code.Types javacTypes;
  protected final TreeMaker maker;
  protected final Names names;
  protected final Symtab symtab;
  protected final ProcessingEnvironment env;

  public TreeBuilder(ProcessingEnvironment env) {
    this.env = env;
    Context context = ((JavacProcessingEnvironment) env).getContext();
    elements = env.getElementUtils();
    modelTypes = env.getTypeUtils();
    javacTypes = com.sun.tools.javac.code.Types.instance(context);
    maker = TreeMaker.instance(context);
    names = Names.instance(context);
    symtab = Symtab.instance(context);
  }

  /**
   * Builds an AST Tree to access the iterator() method of some iterable expression.
   *
   * @param iterableExpr an expression whose type is a subtype of Iterable
   * @return a MemberSelectTree that accesses the iterator() method of the expression
   */
  public MemberSelectTree buildIteratorMethodAccess(ExpressionTree iterableExpr) {
    DeclaredType exprType = (DeclaredType) TypesUtils.upperBound(TreeUtils.typeOf(iterableExpr));
    assert exprType != null : "expression must be of declared type Iterable<>";

    TypeElement exprElement = (TypeElement) exprType.asElement();

    // Find the iterator() method of the iterable type
    Symbol.MethodSymbol iteratorMethod = null;

    for (ExecutableElement method : ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
      if (method.getParameters().isEmpty() && method.getSimpleName().contentEquals("iterator")) {
        iteratorMethod = (Symbol.MethodSymbol) method;
      }
    }

    assert iteratorMethod != null
        : "@AssumeAssertion(nullness): no iterator method declared for expression type";

    Type.MethodType methodType = (Type.MethodType) iteratorMethod.asType();
    Symbol.TypeSymbol methodClass = methodType.asElement();
    DeclaredType iteratorType = (DeclaredType) methodType.getReturnType();
    iteratorType =
        (DeclaredType) javacTypes.asSuper((Type) iteratorType, symtab.iteratorType.asElement());

    int numIterTypeArgs = iteratorType.getTypeArguments().size();
    assert numIterTypeArgs <= 1 : "expected at most one type argument for Iterator";

    if (numIterTypeArgs == 1) {
      TypeMirror elementType = iteratorType.getTypeArguments().get(0);
      // Remove captured type from a wildcard.
      if (elementType instanceof Type.CapturedType) {
        elementType = ((Type.CapturedType) elementType).wildcard;

        iteratorType =
            modelTypes.getDeclaredType(
                (TypeElement) modelTypes.asElement(iteratorType), elementType);
      }
    }

    // Replace the iterator method's generic return type with
    // the actual element type of the expression.
    Type.MethodType updatedMethodType =
        new Type.MethodType(
            com.sun.tools.javac.util.List.nil(),
            (Type) iteratorType,
            com.sun.tools.javac.util.List.nil(),
            methodClass);

    JCTree.JCFieldAccess iteratorAccess =
        (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) iterableExpr, iteratorMethod);
    iteratorAccess.setType(updatedMethodType);

    return iteratorAccess;
  }

  /**
   * Builds an AST Tree to access the hasNext() method of an iterator.
   *
   * @param iteratorExpr an expression whose type is a subtype of Iterator
   * @return a MemberSelectTree that accesses the hasNext() method of the expression
   */
  public MemberSelectTree buildHasNextMethodAccess(ExpressionTree iteratorExpr) {
    DeclaredType exprType = (DeclaredType) TreeUtils.typeOf(iteratorExpr);
    assert exprType != null : "expression must be of declared type Iterator<>";

    TypeElement exprElement = (TypeElement) exprType.asElement();

    // Find the hasNext() method of the iterator type
    Symbol.MethodSymbol hasNextMethod = null;

    for (ExecutableElement method : ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
      if (method.getParameters().isEmpty() && method.getSimpleName().contentEquals("hasNext")) {
        hasNextMethod = (Symbol.MethodSymbol) method;
      }
    }

    assert hasNextMethod != null : "no hasNext method declared for expression type";

    JCTree.JCFieldAccess hasNextAccess =
        (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) iteratorExpr, hasNextMethod);
    hasNextAccess.setType(hasNextMethod.asType());

    return hasNextAccess;
  }

  /**
   * Builds an AST Tree to access the next() method of an iterator.
   *
   * @param iteratorExpr an expression whose type is a subtype of Iterator
   * @return a MemberSelectTree that accesses the next() method of the expression
   */
  public MemberSelectTree buildNextMethodAccess(ExpressionTree iteratorExpr) {
    DeclaredType exprType = (DeclaredType) TreeUtils.typeOf(iteratorExpr);
    assert exprType != null : "expression must be of declared type Iterator<>";

    TypeElement exprElement = (TypeElement) exprType.asElement();

    // Find the next() method of the iterator type
    Symbol.MethodSymbol nextMethod = null;

    for (ExecutableElement method : ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
      if (method.getParameters().isEmpty() && method.getSimpleName().contentEquals("next")) {
        nextMethod = (Symbol.MethodSymbol) method;
      }
    }

    assert nextMethod != null
        : "@AssumeAssertion(nullness): no next method declared for expression type";

    Type.MethodType methodType = (Type.MethodType) nextMethod.asType();
    Symbol.TypeSymbol methodClass = methodType.asElement();
    Type elementType;

    if (exprType.getTypeArguments().isEmpty()) {
      elementType = symtab.objectType;
    } else {
      elementType = (Type) exprType.getTypeArguments().get(0);
    }

    // Replace the next method's generic return type with
    // the actual element type of the expression.
    Type.MethodType updatedMethodType =
        new Type.MethodType(
            com.sun.tools.javac.util.List.nil(),
            elementType,
            com.sun.tools.javac.util.List.nil(),
            methodClass);

    JCTree.JCFieldAccess nextAccess =
        (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) iteratorExpr, nextMethod);
    nextAccess.setType(updatedMethodType);

    return nextAccess;
  }

  /**
   * Builds an AST Tree to dereference the length field of an array.
   *
   * @param expression the array expression whose length is being accessed
   * @return a MemberSelectTree to dereference the length of the array
   */
  public MemberSelectTree buildArrayLengthAccess(ExpressionTree expression) {

    return (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) expression, symtab.lengthVar);
  }

  /**
   * Builds an AST Tree to call a method designated by the argument expression.
   *
   * @param methodExpr an expression denoting a method with no arguments
   * @return a MethodInvocationTree to call the argument method
   */
  public MethodInvocationTree buildMethodInvocation(ExpressionTree methodExpr) {
    return maker.App((JCTree.JCExpression) methodExpr);
  }

  /**
   * Builds an AST Tree to call a method designated by methodExpr, with one argument designated by
   * argExpr.
   *
   * @param methodExpr an expression denoting a method with one argument
   * @param argExpr an expression denoting an argument to the method
   * @return a MethodInvocationTree to call the argument method
   */
  public MethodInvocationTree buildMethodInvocation(
      ExpressionTree methodExpr, ExpressionTree argExpr) {
    return maker.App(
        (JCTree.JCExpression) methodExpr,
        com.sun.tools.javac.util.List.of((JCTree.JCExpression) argExpr));
  }

  /**
   * Builds an AST Tree to declare and initialize a variable, with no modifiers.
   *
   * @param type the type of the variable
   * @param name the name of the variable
   * @param owner the element containing the new symbol
   * @param initializer the initializer expression
   * @return a VariableDeclTree declaring the new variable
   */
  public VariableTree buildVariableDecl(
      TypeMirror type, String name, Element owner, ExpressionTree initializer) {
    DetachedVarSymbol sym =
        new DetachedVarSymbol(0, names.fromString(name), (Type) type, (Symbol) owner);
    VariableTree tree = maker.VarDef(sym, (JCTree.JCExpression) initializer);
    sym.setDeclaration(tree);
    return tree;
  }

  /**
   * Builds an AST Tree to declare and initialize a variable. The type of the variable is specified
   * by a Tree.
   *
   * @param type the type of the variable, as a Tree
   * @param name the name of the variable
   * @param owner the element containing the new symbol
   * @param initializer the initializer expression
   * @return a VariableDeclTree declaring the new variable
   */
  public VariableTree buildVariableDecl(
      Tree type, String name, Element owner, ExpressionTree initializer) {
    Type typeMirror = (Type) TreeUtils.typeOf(type);
    DetachedVarSymbol sym =
        new DetachedVarSymbol(0, names.fromString(name), typeMirror, (Symbol) owner);
    JCTree.JCModifiers mods = maker.Modifiers(0);
    JCTree.JCVariableDecl decl =
        maker.VarDef(mods, sym.name, (JCTree.JCExpression) type, (JCTree.JCExpression) initializer);
    decl.setType(typeMirror);
    decl.sym = sym;
    sym.setDeclaration(decl);
    return decl;
  }

  /**
   * Builds an AST Tree to refer to a variable.
   *
   * @param decl the declaration of the variable
   * @return an IdentifierTree to refer to the variable
   */
  public IdentifierTree buildVariableUse(VariableTree decl) {
    return (IdentifierTree) maker.Ident((JCTree.JCVariableDecl) decl);
  }

  /**
   * Builds an AST Tree to cast the type of an expression.
   *
   * @param type the type to cast to
   * @param expr the expression to be cast
   * @return a cast of the expression to the type
   */
  public TypeCastTree buildTypeCast(TypeMirror type, ExpressionTree expr) {
    return maker.TypeCast((Type) type, (JCTree.JCExpression) expr);
  }

  /**
   * Builds an AST Tree to assign an expression to a variable.
   *
   * @param variable the declaration of the variable to assign to
   * @param expr the expression to be assigned
   * @return a statement assigning the expression to the variable
   */
  public StatementTree buildAssignment(VariableTree variable, ExpressionTree expr) {
    return maker.Assignment(TreeInfo.symbolFor((JCTree) variable), (JCTree.JCExpression) expr);
  }

  /**
   * Builds an AST Tree to assign an RHS expression to an LHS expression.
   *
   * @param lhs the expression to be assigned to
   * @param rhs the expression to be assigned
   * @return a statement assigning the expression to the variable
   */
  public AssignmentTree buildAssignment(ExpressionTree lhs, ExpressionTree rhs) {
    JCTree.JCAssign assign = maker.Assign((JCTree.JCExpression) lhs, (JCTree.JCExpression) rhs);
    assign.setType((Type) TreeUtils.typeOf(lhs));
    return assign;
  }

  /** Builds an AST Tree representing a literal value of primitive or String type. */
  public LiteralTree buildLiteral(Object value) {
    return maker.Literal(value);
  }

  /**
   * Builds an AST Tree to compare two operands with less than.
   *
   * @param left the left operand tree
   * @param right the right operand tree
   * @return a Tree representing "left &lt; right"
   */
  public BinaryTree buildLessThan(ExpressionTree left, ExpressionTree right) {
    JCTree.JCBinary binary =
        maker.Binary(JCTree.Tag.LT, (JCTree.JCExpression) left, (JCTree.JCExpression) right);
    binary.setType((Type) modelTypes.getPrimitiveType(TypeKind.BOOLEAN));
    return binary;
  }

  /**
   * Builds an AST Tree to dereference an array.
   *
   * @param array the array to dereference
   * @param index the index at which to dereference
   * @return a Tree representing the dereference
   */
  public ArrayAccessTree buildArrayAccess(ExpressionTree array, ExpressionTree index) {
    ArrayType arrayType = (ArrayType) TreeUtils.typeOf(array);
    JCTree.JCArrayAccess access =
        maker.Indexed((JCTree.JCExpression) array, (JCTree.JCExpression) index);
    access.setType((Type) arrayType.getComponentType());
    return access;
  }

  /**
   * Builds an AST Tree to refer to a class name.
   *
   * @param elt an element representing the class
   * @return an IdentifierTree referring to the class
   */
  public IdentifierTree buildClassUse(Element elt) {
    return maker.Ident((Symbol) elt);
  }

  /**
   * Builds an AST Tree to access the valueOf() method of boxed type such as Short or Float.
   *
   * @param expr an expression whose type is a boxed type
   * @return a MemberSelectTree that accesses the valueOf() method of the expression
   */
  public MemberSelectTree buildValueOfMethodAccess(Tree expr) {
    TypeMirror boxedType = TreeUtils.typeOf(expr);

    assert TypesUtils.isBoxedPrimitive(boxedType);

    // Find the valueOf(unboxedType) method of the boxed type
    Symbol.MethodSymbol valueOfMethod = getValueOfMethod(env, boxedType);

    Type.MethodType methodType = (Type.MethodType) valueOfMethod.asType();

    JCTree.JCFieldAccess valueOfAccess =
        (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) expr, valueOfMethod);
    valueOfAccess.setType(methodType);

    return valueOfAccess;
  }

  /** Returns the valueOf method of a boxed type such as Short or Float. */
  public static Symbol.MethodSymbol getValueOfMethod(
      ProcessingEnvironment env, TypeMirror boxedType) {
    Symbol.MethodSymbol valueOfMethod = null;

    TypeMirror unboxedType = env.getTypeUtils().unboxedType(boxedType);
    TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();
    for (ExecutableElement method :
        ElementFilter.methodsIn(env.getElementUtils().getAllMembers(boxedElement))) {
      if (method.getSimpleName().contentEquals("valueOf")) {
        List<? extends VariableElement> params = method.getParameters();
        if (params.size() == 1
            && env.getTypeUtils().isSameType(params.get(0).asType(), unboxedType)) {
          valueOfMethod = (Symbol.MethodSymbol) method;
        }
      }
    }

    assert valueOfMethod != null
        : "@AssumeAssertion(nullness): no valueOf method declared for boxed type";
    return valueOfMethod;
  }

  /**
   * Builds an AST Tree to access the *Value() method of a boxed type such as Short or Float, where
   * * is the corresponding primitive type (i.e. shortValue or floatValue).
   *
   * @param expr an expression whose type is a boxed type
   * @return a MemberSelectTree that accesses the *Value() method of the expression
   */
  public MemberSelectTree buildPrimValueMethodAccess(Tree expr) {
    TypeMirror boxedType = TreeUtils.typeOf(expr);
    TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();

    assert TypesUtils.isBoxedPrimitive(boxedType);
    TypeMirror unboxedType = modelTypes.unboxedType(boxedType);

    // Find the *Value() method of the boxed type
    String primValueName = unboxedType.toString() + "Value";
    Symbol.MethodSymbol primValueMethod = null;

    for (ExecutableElement method : ElementFilter.methodsIn(elements.getAllMembers(boxedElement))) {
      if (method.getSimpleName().contentEquals(primValueName) && method.getParameters().isEmpty()) {
        primValueMethod = (Symbol.MethodSymbol) method;
      }
    }

    assert primValueMethod != null
        : "@AssumeAssertion(nullness): no *Value method declared for boxed type";

    Type.MethodType methodType = (Type.MethodType) primValueMethod.asType();

    JCTree.JCFieldAccess primValueAccess =
        (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) expr, primValueMethod);
    primValueAccess.setType(methodType);

    return primValueAccess;
  }

  /** Map public AST Tree.Kinds to internal javac JCTree.Tags. */
  public JCTree.Tag kindToTag(Tree.Kind kind) {
    switch (kind) {
      case AND:
        return JCTree.Tag.BITAND;
      case AND_ASSIGNMENT:
        return JCTree.Tag.BITAND_ASG;
      case ANNOTATION:
        return JCTree.Tag.ANNOTATION;
      case ANNOTATION_TYPE:
        return JCTree.Tag.TYPE_ANNOTATION;
      case ARRAY_ACCESS:
        return JCTree.Tag.INDEXED;
      case ARRAY_TYPE:
        return JCTree.Tag.TYPEARRAY;
      case ASSERT:
        return JCTree.Tag.ASSERT;
      case ASSIGNMENT:
        return JCTree.Tag.ASSIGN;
      case BITWISE_COMPLEMENT:
        return JCTree.Tag.COMPL;
      case BLOCK:
        return JCTree.Tag.BLOCK;
      case BREAK:
        return JCTree.Tag.BREAK;
      case CASE:
        return JCTree.Tag.CASE;
      case CATCH:
        return JCTree.Tag.CATCH;
      case CLASS:
        return JCTree.Tag.CLASSDEF;
      case CONDITIONAL_AND:
        return JCTree.Tag.AND;
      case CONDITIONAL_EXPRESSION:
        return JCTree.Tag.CONDEXPR;
      case CONDITIONAL_OR:
        return JCTree.Tag.OR;
      case CONTINUE:
        return JCTree.Tag.CONTINUE;
      case DIVIDE:
        return JCTree.Tag.DIV;
      case DIVIDE_ASSIGNMENT:
        return JCTree.Tag.DIV_ASG;
      case DO_WHILE_LOOP:
        return JCTree.Tag.DOLOOP;
      case ENHANCED_FOR_LOOP:
        return JCTree.Tag.FOREACHLOOP;
      case EQUAL_TO:
        return JCTree.Tag.EQ;
      case EXPRESSION_STATEMENT:
        return JCTree.Tag.EXEC;
      case FOR_LOOP:
        return JCTree.Tag.FORLOOP;
      case GREATER_THAN:
        return JCTree.Tag.GT;
      case GREATER_THAN_EQUAL:
        return JCTree.Tag.GE;
      case IDENTIFIER:
        return JCTree.Tag.IDENT;
      case IF:
        return JCTree.Tag.IF;
      case IMPORT:
        return JCTree.Tag.IMPORT;
      case INSTANCE_OF:
        return JCTree.Tag.TYPETEST;
      case LABELED_STATEMENT:
        return JCTree.Tag.LABELLED;
      case LEFT_SHIFT:
        return JCTree.Tag.SL;
      case LEFT_SHIFT_ASSIGNMENT:
        return JCTree.Tag.SL_ASG;
      case LESS_THAN:
        return JCTree.Tag.LT;
      case LESS_THAN_EQUAL:
        return JCTree.Tag.LE;
      case LOGICAL_COMPLEMENT:
        return JCTree.Tag.NOT;
      case MEMBER_SELECT:
        return JCTree.Tag.SELECT;
      case METHOD:
        return JCTree.Tag.METHODDEF;
      case METHOD_INVOCATION:
        return JCTree.Tag.APPLY;
      case MINUS:
        return JCTree.Tag.MINUS;
      case MINUS_ASSIGNMENT:
        return JCTree.Tag.MINUS_ASG;
      case MODIFIERS:
        return JCTree.Tag.MODIFIERS;
      case MULTIPLY:
        return JCTree.Tag.MUL;
      case MULTIPLY_ASSIGNMENT:
        return JCTree.Tag.MUL_ASG;
      case NEW_ARRAY:
        return JCTree.Tag.NEWARRAY;
      case NEW_CLASS:
        return JCTree.Tag.NEWCLASS;
      case NOT_EQUAL_TO:
        return JCTree.Tag.NE;
      case OR:
        return JCTree.Tag.BITOR;
      case OR_ASSIGNMENT:
        return JCTree.Tag.BITOR_ASG;
      case PARENTHESIZED:
        return JCTree.Tag.PARENS;
      case PLUS:
        return JCTree.Tag.PLUS;
      case PLUS_ASSIGNMENT:
        return JCTree.Tag.PLUS_ASG;
      case POSTFIX_DECREMENT:
        return JCTree.Tag.POSTDEC;
      case POSTFIX_INCREMENT:
        return JCTree.Tag.POSTINC;
      case PREFIX_DECREMENT:
        return JCTree.Tag.PREDEC;
      case PREFIX_INCREMENT:
        return JCTree.Tag.PREINC;
      case REMAINDER:
        return JCTree.Tag.MOD;
      case REMAINDER_ASSIGNMENT:
        return JCTree.Tag.MOD_ASG;
      case RETURN:
        return JCTree.Tag.RETURN;
      case RIGHT_SHIFT:
        return JCTree.Tag.SR;
      case RIGHT_SHIFT_ASSIGNMENT:
        return JCTree.Tag.SR_ASG;
      case SWITCH:
        return JCTree.Tag.SWITCH;
      case SYNCHRONIZED:
        return JCTree.Tag.SYNCHRONIZED;
      case THROW:
        return JCTree.Tag.THROW;
      case TRY:
        return JCTree.Tag.TRY;
      case TYPE_CAST:
        return JCTree.Tag.TYPECAST;
      case TYPE_PARAMETER:
        return JCTree.Tag.TYPEPARAMETER;
      case UNARY_MINUS:
        return JCTree.Tag.NEG;
      case UNARY_PLUS:
        return JCTree.Tag.POS;
      case UNION_TYPE:
        return JCTree.Tag.TYPEUNION;
      case UNSIGNED_RIGHT_SHIFT:
        return JCTree.Tag.USR;
      case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
        return JCTree.Tag.USR_ASG;
      case VARIABLE:
        return JCTree.Tag.VARDEF;
      case WHILE_LOOP:
        return JCTree.Tag.WHILELOOP;
      case XOR:
        return JCTree.Tag.BITXOR;
      case XOR_ASSIGNMENT:
        return JCTree.Tag.BITXOR_ASG;
      default:
        return JCTree.Tag.NO_TAG;
    }
  }

  /**
   * Builds an AST Tree to perform a binary operation.
   *
   * @param type result type of the operation
   * @param op AST Tree operator
   * @param left the left operand tree
   * @param right the right operand tree
   * @return a Tree representing "left &lt; right"
   */
  public BinaryTree buildBinary(
      TypeMirror type, Tree.Kind op, ExpressionTree left, ExpressionTree right) {
    JCTree.Tag jcOp = kindToTag(op);
    JCTree.JCBinary binary =
        maker.Binary(jcOp, (JCTree.JCExpression) left, (JCTree.JCExpression) right);
    binary.setType((Type) type);
    return binary;
  }

  /**
   * Builds an AST Tree to create a new array with initializers.
   *
   * @param componentType component type of the new array
   * @param elems expression trees of initializers
   * @return a NewArrayTree to create a new array with initializers
   */
  public NewArrayTree buildNewArray(TypeMirror componentType, List<ExpressionTree> elems) {
    List<JCExpression> exprs = CollectionsPlume.mapList(JCExpression.class::cast, elems);

    JCTree.JCNewArray newArray =
        maker.NewArray(
            (JCTree.JCExpression) buildClassUse(((Type) componentType).tsym),
            com.sun.tools.javac.util.List.nil(),
            com.sun.tools.javac.util.List.from(exprs));
    newArray.setType(javacTypes.makeArrayType((Type) componentType));
    return newArray;
  }
}
