/*
 * Copyright 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.PrecompileTaskOptions;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.HasType;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JCharLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFloatLiteral;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
import com.google.gwt.dev.jjs.ast.JMember;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsLiteral;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.lang.LongLib;
import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Predicate;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.base.Strings;
import com.google.gwt.thirdparty.guava.common.collect.Collections2;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * General utilities related to Java AST manipulation.
 */
public class JjsUtils {

  public static boolean closureStyleLiteralsNeeded(PrecompileTaskOptions options) {
    return closureStyleLiteralsNeeded(options.isIncrementalCompileEnabled(),
        options.isClosureCompilerFormatEnabled());
  }

  /**
   * Returns the class literal field name.
   */
  public static String classLiteralFieldNameFromJavahTypeSignatureName(String javahSignatureName) {
    return javahSignatureName + "_classLit";
  }

  public static boolean closureStyleLiteralsNeeded(boolean incremental,
      boolean closureOutputFormat) {
    return !incremental && closureOutputFormat;
  }

  public static String computeSignature(
      String name, List<JType> params, JType returnType, boolean isCtor) {
    StringBuilder sb = new StringBuilder(name);
    sb.append('(');
    for (JType type : params) {
      sb.append(type.getJsniSignatureName());
    }
    sb.append(')');
    if (!isCtor) {
      sb.append(returnType.getJsniSignatureName());
    } else {
      sb.append(" <init>");
    }
    return sb.toString();
  }

  public static String constructManglingSignature(JMethod x, String partialSignature) {
    StringBuilder sb = new StringBuilder(partialSignature);
    sb.append("__");
    for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
      JType type = x.getOriginalParamTypes().get(i);
      sb.append(type.getJavahSignatureName());
    }
    sb.append(x.getOriginalReturnType().getJavahSignatureName());
    return sb.toString();
  }

  /**
   * Returns an instantiation expression for {@code type} using the default constructor,
   * Returns {@code null} if {@code type} does not have a default constructor.
   */
  public static JExpression createDefaultConstructorInstantiation(
      SourceInfo info, JClassType type) {
    /*
     * Find the appropriate (noArg) constructor. In our AST, constructors are
     * instance methods that should be qualified with a new expression.
     */
    JConstructor noArgCtor = (JConstructor) FluentIterable.from(type.getMethods()).firstMatch(
        new Predicate<JMethod>() {
          @Override
          public boolean apply(JMethod method) {
            return method instanceof JConstructor &&  method.getOriginalParamTypes().size() == 0;
          }
        }).orNull();
    if (noArgCtor == null) {
      return null;
    }
    // Call it, using a new expression as a qualifier
    return new JNewInstance(info, noArgCtor);
  }

  /**
   * Creates a synthetic forwarding  stub in {@code type} with the same signature as
   * {@code superTypeMethod} that dispatchs to that method.
   */
  public static JMethod createForwardingMethod(JDeclaredType type,
      JMethod methodToDelegateTo) {
    JMethod forwardingMethod = createEmptyMethodFromExample(type, methodToDelegateTo, false);
    forwardingMethod.setForwarding();

    if (type.isJsNative()) {
      if (methodToDelegateTo.isJsNative()) {
        // Accidental override of native methods on native JsTypes are done by just redeclaring the
        // native method.
        return forwardingMethod;
      }
      // Otherwise the forwarding method is an overlay method with a proper body.
      forwardingMethod.setJsOverlay();
      forwardingMethod.setBody(new JMethodBody(methodToDelegateTo.getSourceInfo()));
    }

    // Create the forwarding body.
    JMethodBody body = (JMethodBody) forwardingMethod.getBody();
    // Invoke methodToDelegate
    JMethodCall forwardingCall = new JMethodCall(methodToDelegateTo.getSourceInfo(),
        new JThisRef(methodToDelegateTo.getSourceInfo(), type),
        methodToDelegateTo);
    forwardingCall.setStaticDispatchOnly();
    // copy params
    for (JParameter p : forwardingMethod.getParams()) {
      forwardingCall.addArg(p.makeRef(p.getSourceInfo()));
    }

    // return statement if not void return type
    body.getBlock().addStmt(makeMethodEndStatement(forwardingMethod.getType(), forwardingCall));
    return forwardingMethod;
  }

  /**
   * Creates a multi expression from a list of expressions, removing expressions that do
   * not have side effects if possible.
   */
  public static JExpression createOptimizedMultiExpression(JExpression... expressions) {
    return createOptimizedMultiExpression(false, Arrays.asList(expressions));
  }

  /**
   * Creates a multi expression from a list of expressions, removing expressions that do
   * not have side effects if possible.
   */
  public static JExpression createOptimizedMultiExpression(boolean ignoringResult,
      List<JExpression> expressions) {

    int numberOfExpressions = expressions.size();
    JExpression result = expressions.get(numberOfExpressions - 1);

    numberOfExpressions = expressions.size();
    if (numberOfExpressions == 0) {
      return new JMultiExpression(SourceOrigin.UNKNOWN);
    }

    expressions =  Lists.newArrayList(Collections2.filter(
        expressions.subList(0, numberOfExpressions - 1),
        Predicates.and(
            Predicates.notNull(),
            new Predicate<JExpression>() {
              @Override
              public boolean apply(JExpression expression) {
                return expression.hasSideEffects();
              }
            })));

    if (result != null && (!ignoringResult || result.hasSideEffects())) {
      expressions.add(result);
    }

    if (expressions.size() == 1) {
      // Do not create a multi expression if it consists only of the result.
      return expressions.iterator().next();
    }

    SourceInfo info = expressions.size() > 0 ? expressions.get(0).getSourceInfo() :
        SourceOrigin.UNKNOWN;
    return new JMultiExpression(info, expressions);
  }

  /**
   * Returns an ast node representing the expression {@code expression != null}.
   */
  public static JExpression createOptimizedNotNullComparison(
      JProgram program, SourceInfo info, JExpression expression) {
    JReferenceType type = (JReferenceType) expression.getType();
    if (type.isNullType()) {
      return program.getLiteralBoolean(false);
    }

    if (!type.canBeNull()) {
      return createOptimizedMultiExpression(expression, program.getLiteralBoolean(true));
    }

    return new JBinaryOperation(info, program.getTypePrimitiveBoolean(),
        JBinaryOperator.NEQ, expression, program.getLiteralNull());
  }

  public static String getIndexedName(JMember member) {
    return member.getEnclosingType().getShortName() + '.' + member.getName();
  }

  /**
   * Creates a synthetic abstract stub in {@code type} with the same signature as
   * {@code superTypeMethod}.
   */
  public static JMethod createSyntheticAbstractStub(JDeclaredType type, JMethod superTypeMethod) {
    assert type.isAbstract();
    assert superTypeMethod.isAbstract();
    return createEmptyMethodFromExample(type, superTypeMethod, true);
  }

  /**
   * Returns a native constructor of a native JsType class.
   */
  public static JConstructor getJsNativeConstructorOrNull(JType type) {
    if (!type.isJsNative() || !(type.getUnderlyingType() instanceof JClassType)) {
      return null;
    }
    JMethod jsConstructor = Iterables.getFirst(Iterables.filter(
        ((JClassType) type).getMethods(), JjsPredicates.IS_JS_CONSTRUCTOR), null);
    assert jsConstructor != null;
    return (JConstructor) jsConstructor;
  }

  /**
   * Returns a description for a type suitable for reporting errors to the users.
   */
  public static String getReadableDescription(JType type) {
    if (type instanceof JArrayType) {
      JArrayType arrayType = (JArrayType) type;
      return getReadableDescription(arrayType.getLeafType()) + Strings.repeat("[]",
          arrayType.getDims());
    }
    return Joiner.on(".").join(type.getCompoundName());
  }

  /**
   * Returns a description for a member suitable for reporting errors to the users.
   */
  public static String getReadableDescription(JMember member) {
    if (member instanceof JField) {
      return String.format("%s %s.%s",
          getReadableDescription(member.getType()),
          getReadableDescription(member.getEnclosingType()),
          member.getName());
    }

    JMethod method = (JMethod) member;
    String printableDescription = "";
    if (!method.isConstructor()) {
      printableDescription += getReadableDescription(method.getType()) + " ";
    }
    printableDescription += String.format("%s.%s(%s)",
        getReadableDescription(method.getEnclosingType()),
        method.getName(),
        Joiner.on(", ").join(
            Iterables.transform(method.getOriginalParamTypes(), new Function<JType, String>() {
                  @Override
                  public String apply(JType type) {
                    return getReadableDescription(type);
                  }
                }
            )));
    return printableDescription;
  }

  public static void replaceMethodBody(JMethod method, JExpression returnValue) {
    JMethodBody body = (JMethodBody) method.getBody();
    JBlock block = body.getBlock();
    block.clear();
    block.addStmt(returnValue.makeReturnStatement());
  }

  /**
   * Returns types from typed nodes.
   */
  public static Iterable<JReferenceType> getExpressionTypes(Iterable<? extends HasType> nodes) {
    if (nodes == null) {
      return Collections.emptyList();
    }
    return FluentIterable.from(nodes).transform(
        new Function<HasType, JReferenceType>() {
          @Override
          public JReferenceType apply(HasType typedNode) {
            return (JReferenceType) typedNode.getType();
          }
        });
  }

  /**
   * Returns true if the method is a synthetic accidental override that trivially dispatches to its
   * same name super.
   */
  public static boolean isJsMemberUnnecessaryAccidentalOverride(JMethod method) {
    // Assumptions on synthethic overrides, if any of these change.
    assert !method.isSyntheticAccidentalOverride() || !method.exposesPackagePrivateMethod();

    if (!method.isSyntheticAccidentalOverride()) {
      return false;
    }

    boolean overridesConcreteJsMethod = Iterables.any(method.getOverriddenMethods(),
        new Predicate<JMethod>() {
          @Override
          public boolean apply(JMethod method) {
            return !method.isAbstract() && method.getJsMemberType() != JsMemberType.NONE;
          }
        });
    // A synthetic accidental override is unnecessary if its due to a JsMethod that does not expose
    // a non JsMember.
    return overridesConcreteJsMethod && !method.exposesNonJsMember();
  }

  /**
   * Mangles a qualified name into a Javah signature.
   */
  public static String javahSignatureFromName(String name) {
    return "L" + mangledNameString(name) + "_2";
  }

  public static String mangleMemberName(String enclosingTypeName, String fieldName) {
    return mangledNameString(enclosingTypeName) + '_' + mangledNameString(fieldName);
  }

  /**
   * Returns an valid identifier for a named Java entity.
   */
  public static String mangledNameString(HasName hasName) {
    return mangledNameString(hasName.getName());
  }

  /**
   * Returns an valid identifier for a named Java entity.
   */
  public static String mangledNameString(String name) {
    return name.replaceAll("_", "_1").replace('.', '_');
  }

  /**
   * Returns the ending statement for a method based on an expression. If the return type is void
   * then the ending statement just executes the expression otherwise it returns it.
   */
  public static JStatement makeMethodEndStatement(JType returnType, JExpression expression) {
    // TODO(rluble): Check if something needs to be done here regarding boxing/unboxing/coercions
    // when one of the types of expression and returnType is a boxed type and the other a primitive
    // type or both are primitive of differnent coerceable types. Add the proper tests first.
    return returnType == JPrimitiveType.VOID ?
        expression.makeStatement() :
        expression.makeReturnStatement();
  }

  /**
   * Translates a Java literal into a JavaScript literal.
   */
  public static JsLiteral translateLiteral(JLiteral literal) {
    return translatorByLiteralClass.get(literal.getClass()).translate(literal);
  }

  static void synthesizeStaticInitializerChain(
      JDeclaredType type, Iterable<JInterfaceType> superInterfacesRequiringStaticInitialization) {
    // Implement static initialization as described in (Java 8) JLS 12.4.2.
    List<JStatement> superClinitCalls = Lists.newArrayList();
    SourceInfo sourceInfo = type.getSourceInfo();

    // First call the static initializer for the superclass.
    JClassType superClass = type.getSuperClass();
    if (superClass != null) {
      superClinitCalls.add(
          new JMethodCall(sourceInfo, null, superClass.getClinitMethod()).makeStatement());
    }

    // Recurse over interfaces in preorder initializing the ones that have default methods.
    for (JInterfaceType interfaceType : superInterfacesRequiringStaticInitialization) {
      superClinitCalls.add(
          new JMethodCall(sourceInfo, null, interfaceType.getClinitMethod()).makeStatement());
    }

    JMethodBody body = (JMethodBody) type.getClinitMethod().getBody();
    body.getBlock().getStatements().addAll(0, superClinitCalls);
  }

  private static Map<Class<? extends JLiteral>, LiteralTranslators> translatorByLiteralClass =
      new ImmutableMap.Builder<Class<? extends JLiteral>, LiteralTranslators>()
          .put(JBooleanLiteral.class, LiteralTranslators.BOOLEAN_LITERAL_TRANSLATOR)
          .put(JCharLiteral.class, LiteralTranslators.CHAR_LITERAL_TRANSLATOR)
          .put(JFloatLiteral.class, LiteralTranslators.FLOAT_LITERAL_TRANSLATOR)
          .put(JDoubleLiteral.class, LiteralTranslators.DOUBLE_LITERAL_TRANSLATOR)
          .put(JIntLiteral.class, LiteralTranslators.INT_LITERAL_TRANSLATOR)
          .put(JLongLiteral.class, LiteralTranslators.LONG_LITERAL_TRANSLATOR)
          .put(JNullLiteral.class, LiteralTranslators.NULL_LITERAL_TRANSLATOR)
          .put(JStringLiteral.class, LiteralTranslators.STRING_LITERAL_TRANSLATOR)
          .build();

  /**
   * Return true if the statement is an empty block.
   */
  public static boolean isEmptyBlock(JStatement stmt) {
    if (stmt == null) {
      return true;
    }
    return (stmt instanceof JBlock && ((JBlock) stmt).getStatements().isEmpty());
  }

  private enum LiteralTranslators {
    BOOLEAN_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return JsBooleanLiteral.get(((JBooleanLiteral) literal).getValue());
      }
    },
    CHAR_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return new JsNumberLiteral(literal.getSourceInfo(), ((JCharLiteral) literal).getValue());
      }
    },
    FLOAT_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return new JsNumberLiteral(literal.getSourceInfo(), ((JFloatLiteral) literal).getValue());
      }
    },
    DOUBLE_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return new JsNumberLiteral(literal.getSourceInfo(), ((JDoubleLiteral) literal).getValue());
      }
    },
    INT_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return new JsNumberLiteral(literal.getSourceInfo(), ((JIntLiteral) literal).getValue());
      }
    },
    LONG_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        SourceInfo sourceInfo = literal.getSourceInfo();
        long[] values = LongLib.getAsLongArray(((JLongLiteral) literal).getValue());
        if (values.length == 1) {
          return new JsNumberLiteral(literal.getSourceInfo(), ((JLongLiteral) literal).getValue());
        }
        JsObjectLiteral.Builder objectLiteralBuilder = JsObjectLiteral.builder(sourceInfo)
            .setInternable();

        assert values.length == longComponentNames.length;
        for (int i = 0; i < longComponentNames.length; i++) {
          addPropertyToObject(sourceInfo, longComponentNames[i], values[i], objectLiteralBuilder);
        }
        return objectLiteralBuilder.build();
      }
    },
    STRING_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return new JsStringLiteral(literal.getSourceInfo(), ((JStringLiteral) literal).getValue());
      }
    },
    NULL_LITERAL_TRANSLATOR() {
      @Override
      JsLiteral translate(JExpression literal) {
        return JsNullLiteral.INSTANCE;
      }
    };

    private static String[] longComponentNames = { "l", "m", "h" };

    abstract JsLiteral translate(JExpression literal);
  }

  private static void addPropertyToObject(SourceInfo sourceInfo, String propertyName,
      long propertyValue, JsObjectLiteral.Builder objectLiteralBuilder) {
    JsExpression value = new JsNumberLiteral(sourceInfo, propertyValue);
    objectLiteralBuilder.add(new JsNameRef(sourceInfo, propertyName), value);
  }

  private static JMethod createEmptyMethodFromExample(
      JDeclaredType inType, JMethod exampleMethod, boolean isAbstract) {
    JMethod emptyMethod = new JMethod(exampleMethod.getSourceInfo(), exampleMethod.getName(),
        inType, exampleMethod.getType(), isAbstract, false, false, exampleMethod.getAccess());
    emptyMethod.addThrownExceptions(exampleMethod.getThrownExceptions());
    emptyMethod.setSynthetic();
    // Copy parameters.
    for (JParameter param : exampleMethod.getParams()) {
      emptyMethod.cloneParameter(param);
    }
    // If the enclosing type is native, make sure the synthetic empty method is native by leaving
    // the body = null.
    if (!inType.isJsNative()) {
      JMethodBody body = new JMethodBody(exampleMethod.getSourceInfo());
      emptyMethod.setBody(body);
    }
    emptyMethod.freezeParamTypes();
    inType.addMethod(emptyMethod);
    return emptyMethod;
  }

  /**
   * Extracts the this(..) or super(..) call from a statement if the statement is of the expected
   * form. Otherwise returns null.
   */
  public static JMethodCall getThisOrSuperConstructorCall(
      JStatement statement) {
    if (!(statement instanceof JExpressionStatement)) {
      return null;
    }

    JExpressionStatement expressionStatement = (JExpressionStatement) statement;
    if (!(expressionStatement.getExpr() instanceof JMethodCall)
        || expressionStatement.getExpr() instanceof JNewInstance) {
      return null;
    }

    JMethodCall call = (JMethodCall) expressionStatement.getExpr();
    if (call.getTarget() instanceof JConstructor && call.isStaticDispatchOnly()) {
      return call;
    }
    return null;
  }

  /**
   * Gets all the supertypes of {@code type}.
   */

  public static Set<JDeclaredType> getSupertypes(JDeclaredType type) {
    Set<JDeclaredType> superTypes = Sets.newHashSet();
    addAllSuperTypes(type, superTypes);
    return superTypes;
  }

  /**
   * Adds all the supertypes of {@code type} to {@code types}.
   */
  public static void addAllSuperTypes(JDeclaredType type, Set<JDeclaredType> types) {
    if (type.getSuperClass() != null) {
      types.add(type.getSuperClass());
      addAllSuperTypes(type.getSuperClass(), types);
    }
    for (JInterfaceType interfaceType : type.getImplements()) {
      types.add(interfaceType);
      addAllSuperTypes(interfaceType, types);
    }
  }

  /**
   * Returns the JsConstructor for a class or null if it does not have any.
   */
  public static JConstructor getJsConstructor(JDeclaredType type) {
    return
        FluentIterable
            .from(type.getConstructors())
            .filter(new Predicate<JConstructor>() {
              @Override
              public boolean apply(JConstructor constructor) {
                return constructor.isJsConstructor();
              }
            }).first().orNull();
  }

  /**
   * Returns the constructor which this constructor delegates or null if none.
   */
  public static JConstructor getDelegatedThisOrSuperConstructor(JConstructor constructor) {
    JStatement contructorInvocaton = FluentIterable
            .from(constructor.getBody().getStatements())
            .filter(new Predicate<JStatement>() {
              @Override
              public boolean apply(JStatement statement) {
                return getThisOrSuperConstructorCall(statement) != null;
              }
            }).first().orNull();

    return contructorInvocaton != null
        ? (JConstructor) getThisOrSuperConstructorCall(contructorInvocaton).getTarget()
        : null;
  }

  /**
   * Returns the constructor which all others delegate to if any, otherwise null.
   */
  public static JConstructor getPrimaryConstructor(final JDeclaredType type) {
    List<JConstructor> delegatedSuperConstructors = FluentIterable
        .from(type.getConstructors())
        .filter(new Predicate<JConstructor>() {
          @Override
          public boolean apply(JConstructor constructor) {
            // Calls super constructor.
            return getDelegatedThisOrSuperConstructor(constructor).getEnclosingType() != type;
          }
        })
        .limit(2)
        .toList();
    if (delegatedSuperConstructors.size() == 1) {
      return delegatedSuperConstructors.get(0);
    }
    return null;
  }

  /**
   * Returns the nearest native superclass of {@code type} if any, null otherwise.
   */
  public static JClassType getNativeSuperClassOrNull(JDeclaredType type) {
    JClassType superClass = type.getSuperClass();
    if (superClass == null || superClass.isJsNative()) {
      return superClass;
    }
    return getNativeSuperClassOrNull(superClass);
  }

  /**
   * Whether or not to use the JsName when implementing this member.
   *
   * <p>A member should only require a JsName when a JsName has been assigned and the compilation
   * has been configured to honor those names.
   * */
  public static boolean requiresJsName(JMember member) {
    // JsFunction interfaces and  implementations do not have JsNames but canBeReferencedExternally
    // or canBeImplementedExternally.
    return member.getJsMemberType() != JsMemberType.NONE
        && (member.canBeImplementedExternally() || member.canBeReferencedExternally());
  }

  private JjsUtils() {
  }
}