// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph.lens;

import static com.android.tools.r8.utils.collections.ThrowingSet.isThrowingSet;
import static com.google.common.base.Predicates.alwaysFalse;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMergerGraphLens;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.ir.optimize.CustomLensCodeRewriter;
import com.android.tools.r8.ir.optimize.enums.EnumUnboxingLens;
import com.android.tools.r8.optimize.MemberRebindingIdentityLens;
import com.android.tools.r8.optimize.MemberRebindingLens;
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.verticalclassmerging.VerticalClassMergerGraphLens;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;

/**
 * A GraphLens implements a virtual view on top of the graph, used to delay global rewrites until
 * later IR processing stages.
 *
 * <p>Valid remappings are limited to the following operations:
 *
 * <ul>
 *   <li>Mapping a classes type to one of the super/subtypes.
 *   <li>Renaming private methods/fields.
 *   <li>Moving methods/fields to a super/subclass.
 *   <li>Replacing method/field references by the same method/field on a super/subtype
 *   <li>Moved methods might require changed invocation type at the call site
 * </ul>
 *
 * Note that the latter two have to take visibility into account.
 */
public abstract class GraphLens {

  public abstract static class Builder {

    protected final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap =
        BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();

    protected Builder() {}

    @SuppressWarnings("ReferenceEquality")
    public void move(DexMethod from, DexMethod to) {
      if (from == to) {
        return;
      }
      methodMap.put(from, to);
    }

    public abstract GraphLens build(AppView<?> appView);
  }

  /**
   * Intentionally package private. All graph lenses except for {@link IdentityGraphLens} should
   * inherit from {@link NonIdentityGraphLens}.
   */
  GraphLens() {}

  public boolean isSyntheticFinalizationGraphLens() {
    return false;
  }

  @Deprecated
  public final DexType getOriginalType(DexType type) {
    GraphLens appliedLens = getIdentityLens();
    return getOriginalType(type, appliedLens);
  }

  public final DexType getOriginalType(DexType type, GraphLens appliedLens) {
    return getOriginalReference(type, appliedLens, NonIdentityGraphLens::getPreviousClassType);
  }

  public abstract Iterable<DexType> getOriginalTypes(DexType type);

  @Deprecated
  public final DexField getOriginalFieldSignature(DexField field) {
    GraphLens appliedLens = getIdentityLens();
    return getOriginalFieldSignature(field, appliedLens);
  }

  public final DexField getOriginalFieldSignature(DexField field, GraphLens appliedLens) {
    return getOriginalReference(
        field, appliedLens, NonIdentityGraphLens::getPreviousFieldSignature);
  }

  @Deprecated
  public final DexMethod getOriginalMethodSignature(DexMethod method) {
    GraphLens appliedLens = getIdentityLens();
    return getOriginalMethodSignature(method, appliedLens);
  }

  public final DexMethod getOriginalMethodSignature(DexMethod method, GraphLens appliedLens) {
    return getOriginalReference(
        method, appliedLens, NonIdentityGraphLens::getPreviousMethodSignature);
  }

  public final DexMethod getOriginalMethodSignatureForMapping(DexMethod method) {
    GraphLens appliedLens = getIdentityLens();
    return getOriginalReference(
        method, appliedLens, NonIdentityGraphLens::getPreviousMethodSignatureForMapping);
  }

  private <T extends DexReference> T getOriginalReference(
      T reference, GraphLens appliedLens, BiFunction<NonIdentityGraphLens, T, T> previousFn) {
    GraphLens current = this;
    T original = reference;
    while (current.isNonIdentityLens() && current != appliedLens) {
      NonIdentityGraphLens nonIdentityLens = current.asNonIdentityLens();
      original = previousFn.apply(nonIdentityLens, original);
      current = nonIdentityLens.getPrevious();
    }
    return original;
  }

  public final DexReference getRenamedReference(
      DexReference originalReference, GraphLens codeLens) {
    return originalReference.apply(
        clazz -> lookupType(clazz, codeLens),
        field -> getRenamedFieldSignature(field, codeLens),
        method -> getRenamedMethodSignature(method, codeLens));
  }

  @Deprecated
  public final DexField getRenamedFieldSignature(DexField originalField) {
    GraphLens appliedLens = getIdentityLens();
    return getRenamedFieldSignature(originalField, appliedLens);
  }

  public final DexField getRenamedFieldSignature(DexField originalField, GraphLens appliedLens) {
    return getRenamedReference(
        originalField, appliedLens, NonIdentityGraphLens::getNextFieldSignature);
  }

  public final DexMember<?, ?> getRenamedMemberSignature(
      DexMember<?, ?> originalMember, GraphLens codeLens) {
    return originalMember.isDexField()
        ? getRenamedFieldSignature(originalMember.asDexField(), codeLens)
        : getRenamedMethodSignature(originalMember.asDexMethod(), codeLens);
  }

  @Deprecated
  public final DexMethod getRenamedMethodSignature(DexMethod originalMethod) {
    GraphLens appliedLens = getIdentityLens();
    return getRenamedMethodSignature(originalMethod, appliedLens);
  }

  public final DexMethod getRenamedMethodSignature(DexMethod method, GraphLens appliedLens) {
    return getRenamedReference(method, appliedLens, NonIdentityGraphLens::getNextMethodSignature);
  }

  private <T extends DexReference> T getRenamedReference(
      T reference, GraphLens appliedLens, BiFunction<NonIdentityGraphLens, T, T> nextFn) {
    return getRenamedReference(reference, appliedLens, nextFn, alwaysFalse());
  }

  private <T extends DexReference> T getRenamedReference(
      T reference,
      GraphLens appliedLens,
      BiFunction<NonIdentityGraphLens, T, T> nextFn,
      Predicate<T> stoppingCriterion) {
    GraphLens current = this;
    Deque<NonIdentityGraphLens> lenses = new ArrayDeque<>();
    while (current.isNonIdentityLens() && current != appliedLens) {
      NonIdentityGraphLens nonIdentityLens = current.asNonIdentityLens();
      lenses.addLast(nonIdentityLens);
      current = nonIdentityLens.getPrevious();
    }
    while (!lenses.isEmpty()) {
      NonIdentityGraphLens lens = lenses.removeLast();
      reference = nextFn.apply(lens, reference);
      if (stoppingCriterion.test(reference)) {
        break;
      }
    }
    return reference;
  }

  @SuppressWarnings("ReferenceEquality")
  // Predicate indicating if a rewritten reference is a simple renaming, meaning the move from one
  // reference to another is simply either just a renaming or/also renaming of the references. In
  // other words, the content of the definition, including the definition of all of its members is
  // the same modulo the renaming.
  public <T extends DexReference> boolean isSimpleRenaming(T from, T to) {
    assert from != to;
    return false;
  }

  public abstract String lookupPackageName(String pkg);

  public final DexType lookupClassType(DexType type, GraphLens appliedLens) {
    return getRenamedReference(
        type, appliedLens, NonIdentityGraphLens::getNextClassType, DexType::isPrimitiveType);
  }

  @Deprecated
  public DexType lookupType(DexType type) {
    GraphLens appliedLens = getIdentityLens();
    return lookupType(type, appliedLens);
  }

  public abstract DexType lookupType(DexType type, GraphLens appliedLens);

  @Deprecated
  public final MethodLookupResult lookupInvokeDirect(DexMethod method, ProgramMethod context) {
    return lookupMethod(method, context.getReference(), InvokeType.DIRECT);
  }

  public final MethodLookupResult lookupInvokeDirect(
      DexMethod method, ProgramMethod context, GraphLens codeLens) {
    return lookupMethod(method, context.getReference(), InvokeType.DIRECT, codeLens);
  }

  @Deprecated
  public final MethodLookupResult lookupInvokeInterface(DexMethod method, ProgramMethod context) {
    return lookupMethod(method, context.getReference(), InvokeType.INTERFACE);
  }

  public final MethodLookupResult lookupInvokeInterface(
      DexMethod method, ProgramMethod context, GraphLens codeLens) {
    return lookupMethod(method, context.getReference(), InvokeType.INTERFACE, codeLens);
  }

  @Deprecated
  public final MethodLookupResult lookupInvokeStatic(DexMethod method, ProgramMethod context) {
    return lookupMethod(method, context.getReference(), InvokeType.STATIC);
  }

  public final MethodLookupResult lookupInvokeStatic(
      DexMethod method, ProgramMethod context, GraphLens codeLens) {
    return lookupMethod(method, context.getReference(), InvokeType.STATIC, codeLens);
  }

  @Deprecated
  public final MethodLookupResult lookupInvokeSuper(DexMethod method, ProgramMethod context) {
    return lookupMethod(method, context.getReference(), InvokeType.SUPER);
  }

  public final MethodLookupResult lookupInvokeSuper(
      DexMethod method, ProgramMethod context, GraphLens codeLens) {
    return lookupMethod(method, context.getReference(), InvokeType.SUPER, codeLens);
  }

  @Deprecated
  public final MethodLookupResult lookupInvokeVirtual(DexMethod method, ProgramMethod context) {
    return lookupMethod(method, context.getReference(), InvokeType.VIRTUAL);
  }

  public final MethodLookupResult lookupInvokeVirtual(
      DexMethod method, ProgramMethod context, GraphLens codeLens) {
    return lookupMethod(method, context.getReference(), InvokeType.VIRTUAL, codeLens);
  }

  @Deprecated
  @SuppressWarnings("InlineMeSuggester")
  public final MethodLookupResult lookupMethod(
      DexMethod method, DexMethod context, InvokeType type) {
    return lookupMethod(method, context, type, null);
  }

  /**
   * Lookup a rebound or non-rebound method reference using the current graph lens.
   *
   * @param codeLens Specifies the graph lens which has already been applied to the code object. The
   *     lookup procedure will not recurse beyond this graph lens to ensure that each mapping is
   *     applied at most once.
   *     <p>Note: since the compiler currently inserts {@link ClearCodeRewritingGraphLens} it is
   *     generally valid to pass null for the {@param codeLens}. The removal of {@link
   *     ClearCodeRewritingGraphLens} is tracked by b/202368283. After this is removed, the compiler
   *     should generally use the result of calling {@link AppView#codeLens()}.
   */
  public abstract MethodLookupResult lookupMethod(
      DexMethod method, DexMethod context, InvokeType type, GraphLens codeLens);

  protected abstract MethodLookupResult internalLookupMethod(
      DexMethod reference,
      DexMethod context,
      InvokeType type,
      GraphLens codeLens,
      LookupMethodContinuation continuation);

  public interface LookupMethodContinuation {

    MethodLookupResult lookupMethod(MethodLookupResult previous);
  }

  public final RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
      DexMethod method) {
    return lookupPrototypeChangesForMethodDefinition(method, null);
  }

  public abstract RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
      DexMethod method, GraphLens codeLens);

  @Deprecated
  @SuppressWarnings("InlineMeSuggester")
  public final DexField lookupField(DexField field) {
    return lookupField(field, null);
  }

  /** Lookup a rebound or non-rebound field reference using the current graph lens. */
  public DexField lookupField(DexField field, GraphLens codeLens) {
    // Lookup the field using the graph lens and return the (non-rebound) reference from the lookup
    // result.
    return lookupFieldResult(field, codeLens).getReference();
  }

  /** Lookup a rebound or non-rebound field reference using the current graph lens. */
  public final FieldLookupResult lookupFieldResult(DexField field) {
    // Lookup the field using the graph lens and return the lookup result.
    return lookupFieldResult(field, null);
  }

  /** Lookup a rebound or non-rebound field reference using the current graph lens. */
  public final FieldLookupResult lookupFieldResult(DexField field, GraphLens codeLens) {
    // Lookup the field using the graph lens and return the lookup result.
    return internalLookupField(field, codeLens, x -> x);
  }

  protected abstract FieldLookupResult internalLookupField(
      DexField reference, GraphLens codeLens, LookupFieldContinuation continuation);

  interface LookupFieldContinuation {

    FieldLookupResult lookupField(FieldLookupResult previous);
  }

  // The method lookupMethod() maps a pair INVOKE=(method signature, invoke type) to a new pair
  // INVOKE'=(method signature', invoke type'). This mapping can be context sensitive, meaning that
  // the result INVOKE' depends on where the invocation INVOKE is in the program. This is, for
  // example, used by the vertical class merger to translate invoke-super instructions that hit
  // a method in the direct super class to invoke-direct instructions after class merging.
  //
  // This method can be used to determine if a graph lens is context sensitive. If a graph lens
  // is context insensitive, it is safe to invoke lookupMethod() without a context (or to pass null
  // as context). Trying to invoke a context sensitive graph lens without a context will lead to
  // an assertion error.
  public abstract boolean isContextFreeForMethods(GraphLens codeLens);

  public boolean verifyIsContextFreeForMethod(DexMethod method, GraphLens codeLens) {
    assert isContextFreeForMethods(codeLens);
    return true;
  }

  public static GraphLens getIdentityLens() {
    return IdentityGraphLens.getInstance();
  }

  public boolean hasCodeRewritings() {
    return true;
  }

  public boolean hasCustomLensCodeRewriter() {
    return false;
  }

  public CustomLensCodeRewriter getCustomLensCodeRewriter() {
    assert hasCustomLensCodeRewriter();
    return null;
  }

  public boolean isAccessModifierLens() {
    return false;
  }

  public boolean isAppliedLens() {
    return false;
  }

  public boolean isArgumentPropagatorGraphLens() {
    return false;
  }

  public final boolean isClassMergerLens() {
    return isHorizontalClassMergerGraphLens() || isVerticalClassMergerLens();
  }

  public boolean isClearCodeRewritingLens() {
    return false;
  }

  public boolean isEnumUnboxerLens() {
    return false;
  }

  public EnumUnboxingLens asEnumUnboxerLens() {
    return null;
  }

  public boolean isNumberUnboxerLens() {
    return false;
  }

  public boolean isHorizontalClassMergerGraphLens() {
    return false;
  }

  public HorizontalClassMergerGraphLens asHorizontalClassMergerGraphLens() {
    return null;
  }

  public abstract boolean isIdentityLens();

  public abstract boolean isIdentityLensForFields(GraphLens codeLens);

  public boolean isMemberRebindingLens() {
    return false;
  }

  public MemberRebindingLens asMemberRebindingLens() {
    return null;
  }

  public boolean isMemberRebindingIdentityLens() {
    return false;
  }

  public MemberRebindingIdentityLens asMemberRebindingIdentityLens() {
    return null;
  }

  public abstract boolean isNonIdentityLens();

  public NonIdentityGraphLens asNonIdentityLens() {
    return null;
  }

  public boolean isProtoNormalizerLens() {
    return false;
  }

  public boolean isRepackagingLens() {
    return false;
  }

  public boolean isVerticalClassMergerLens() {
    return false;
  }

  public VerticalClassMergerGraphLens asVerticalClassMergerLens() {
    return null;
  }

  @SuppressWarnings("ReferenceEquality")
  public boolean assertFieldsNotModified(Iterable<DexEncodedField> fields) {
    for (DexEncodedField field : fields) {
      DexField reference = field.getReference();
      assert getRenamedFieldSignature(reference) == reference;
    }
    return true;
  }

  public Map<DexCallSite, ProgramMethodSet> rewriteCallSites(
      Map<DexCallSite, ProgramMethodSet> callSites,
      DexDefinitionSupplier definitions,
      Timing timing) {
    timing.begin("Rewrite call sites");
    Map<DexCallSite, ProgramMethodSet> result = new IdentityHashMap<>();
    LensCodeRewriterUtils rewriter = new LensCodeRewriterUtils(definitions, this, null);
    callSites.forEach(
        (callSite, contexts) -> {
          for (ProgramMethod context : contexts.rewrittenWithLens(definitions, this)) {
            DexCallSite rewrittenCallSite = rewriter.rewriteCallSite(callSite, context);
            result
                .computeIfAbsent(rewrittenCallSite, ignore -> ProgramMethodSet.create())
                .add(context);
          }
        });
    timing.end();
    return result;
  }

  @SuppressWarnings("ReferenceEquality")
  public Set<DexField> rewriteFields(Set<DexField> fields, Timing timing) {
    timing.begin("Rewrite fields");
    GraphLens appliedLens = getIdentityLens();
    Set<DexField> rewrittenFields;
    if (isIdentityLensForFields(appliedLens)) {
      assert verifyIsIdentityLensForFields(fields, appliedLens);
      rewrittenFields = fields;
    } else {
      rewrittenFields = null;
      for (DexField field : fields) {
        DexField rewrittenField = getRenamedFieldSignature(field, appliedLens);
        // If rewrittenFields is non-null we have previously seen a change and need to record the
        // field no matter what.
        if (rewrittenFields != null) {
          rewrittenFields.add(rewrittenField);
          continue;
        }
        // If the field has not been rewritten then we can reuse the input set.
        if (rewrittenField == field) {
          continue;
        }
        // Otherwise add the rewritten field and all previous fields to a new set.
        rewrittenFields = SetUtils.newIdentityHashSet(fields.size());
        CollectionUtils.forEachUntilExclusive(fields, rewrittenFields::add, field);
        rewrittenFields.add(rewrittenField);
      }
      if (rewrittenFields == null) {
        rewrittenFields = fields;
      } else {
        rewrittenFields =
            SetUtils.trimCapacityOfIdentityHashSetIfSizeLessThan(rewrittenFields, fields.size());
      }
    }
    timing.end();
    return rewrittenFields;
  }

  @SuppressWarnings("ReferenceEquality")
  private boolean verifyIsIdentityLensForFields(
      Collection<DexField> fields, GraphLens appliedLens) {
    for (DexField field : fields) {
      assert lookupField(field, appliedLens) == field;
    }
    return true;
  }

  @SuppressWarnings("unchecked")
  public <T extends DexReference> T rewriteReference(T reference) {
    return rewriteReference(reference, null);
  }

  @SuppressWarnings("unchecked")
  public <T extends DexReference> T rewriteReference(T reference, GraphLens codeLens) {
    return (T)
        reference.apply(
            type -> lookupType(type, codeLens),
            field -> getRenamedFieldSignature(field, codeLens),
            method -> getRenamedMethodSignature(method, codeLens));
  }

  public <T extends DexReference> Set<T> rewriteReferences(Set<T> references) {
    if (isThrowingSet(references)) {
      return references;
    }
    Set<T> result = SetUtils.newIdentityHashSet(references.size());
    for (T reference : references) {
      result.add(rewriteReference(reference));
    }
    return result;
  }

  public <R extends DexReference, T> Map<R, T> rewriteReferenceKeys(
      Map<R, T> map, BiFunction<R, List<T>, T> merge) {
    Map<R, T> result = new IdentityHashMap<>();
    Map<R, List<T>> needsMerge = new IdentityHashMap<>();
    map.forEach(
        (reference, value) -> {
          R rewrittenReference = rewriteReference(reference);
          List<T> unmergedValues = needsMerge.get(rewrittenReference);
          if (unmergedValues != null) {
            unmergedValues.add(value);
          } else {
            T existingValue = result.put(rewrittenReference, value);
            if (existingValue != null) {
              // Remove this for now and let the merge function decide when all colliding values are
              // known.
              needsMerge.put(rewrittenReference, ListUtils.newArrayList(existingValue, value));
              result.remove(rewrittenReference);
            }
          }
        });
    needsMerge.forEach(
        (rewrittenReference, unmergedValues) -> {
          T mergedValue = merge.apply(rewrittenReference, unmergedValues);
          if (mergedValue != null) {
            result.put(rewrittenReference, mergedValue);
          }
        });
    return result;
  }

  public <T extends DexReference> Object2BooleanMap<T> rewriteReferenceKeys(
      Object2BooleanMap<T> map) {
    Object2BooleanMap<T> result = new Object2BooleanArrayMap<>();
    for (Object2BooleanMap.Entry<T> entry : map.object2BooleanEntrySet()) {
      result.put(rewriteReference(entry.getKey()), entry.getBooleanValue());
    }
    return result;
  }

  public <T> ImmutableMap<DexField, T> rewriteFieldKeys(Map<DexField, T> map) {
    ImmutableMap.Builder<DexField, T> builder = ImmutableMap.builder();
    map.forEach((field, value) -> builder.put(getRenamedFieldSignature(field), value));
    return builder.build();
  }

  public ImmutableSet<DexType> rewriteTypes(Set<DexType> types) {
    ImmutableSet.Builder<DexType> builder = new ImmutableSet.Builder<>();
    for (DexType type : types) {
      builder.add(lookupType(type));
    }
    return builder.build();
  }

  public <T> Map<DexType, T> rewriteTypeKeys(Map<DexType, T> map, BiFunction<T, T, T> merge) {
    Map<DexType, T> newMap = new IdentityHashMap<>();
    map.forEach(
        (type, value) -> {
          DexType rewrittenType = lookupType(type);
          T previousValue = newMap.get(rewrittenType);
          newMap.put(
              rewrittenType, previousValue != null ? merge.apply(value, previousValue) : value);
        });
    return newMap;
  }

  public boolean verifyMappingToOriginalProgram(
      AppView<?> appView, DexApplication originalApplication) {
    Iterable<DexProgramClass> classes = appView.appInfo().classesWithDeterministicOrder();
    // Collect all original fields and methods for efficient querying.
    Set<DexField> originalFields = Sets.newIdentityHashSet();
    Set<DexMethod> originalMethods = Sets.newIdentityHashSet();
    for (DexProgramClass clazz : originalApplication.classes()) {
      for (DexEncodedField field : clazz.fields()) {
        originalFields.add(field.getReference());
      }
      for (DexEncodedMethod method : clazz.methods()) {
        originalMethods.add(method.getReference());
      }
    }

    // Check that all fields and methods in the generated program can be mapped back to one of the
    // original fields or methods.
    for (DexProgramClass clazz : classes) {
      if (appView.appInfo().getSyntheticItems().isSyntheticClass(clazz)) {
        continue;
      }
      for (DexEncodedField field : clazz.fields()) {
        if (field.isD8R8Synthesized()) {
          // Fields synthesized by D8/R8 may not be mapped.
          continue;
        }
        DexField originalField = getOriginalFieldSignature(field.getReference());
        assert originalFields.contains(originalField)
            : "Unable to map field `"
                + field.getReference().toSourceString()
                + "` back to original program";
      }
      for (DexEncodedMethod method : clazz.methods()) {
        // Methods synthesized by D8/R8 are not mapped, but all non-synthesized must be originals.
        assert method.isD8R8Synthesized() || originalMethods.contains(method.getReference());
      }
    }

    return true;
  }
}
